Compare commits

..

No commits in common. "main" and "feature/poet-book-editors" have entirely different histories.

4 changed files with 14 additions and 38 deletions

View File

@ -56,8 +56,6 @@ import { siteUrl } from '../lib/site-url';
if (localStorage.getItem('divan-font') === 'nastaliq') document.documentElement.classList.add('nastaliq');
const w = localStorage.getItem('divan-weight'); // Naskh's weight (400-700), heavier for small screens
if (w) document.documentElement.style.setProperty('--naskh-weight', w);
const z = localStorage.getItem('divan-size'); // text size in % (100 by default), every page scales with it
if (z) document.documentElement.style.setProperty('--text-size', z + '%');
const t = localStorage.getItem('divan-theme');
if (t) document.documentElement.dataset.theme = t;
const pal = localStorage.getItem('divan-palette'); // sepia when unset
@ -98,8 +96,6 @@ import { siteUrl } from '../lib/site-url';
<div class="seg"><button type="button" data-font="naskh">نسخ</button><button type="button" data-font="nastaliq" class="f-nastaliq">نستعلیق</button></div>
<label class="weight"><span>نسخ کی موٹائی</span>
<input type="range" min="400" max="700" step="100" value="400" data-weight aria-label="نسخ کی موٹائی" /></label>
<label class="weight"><span>حروف کا سائز</span>
<input type="range" min="90" max="150" step="10" value="100" data-size aria-label="حروف کا سائز" /></label>
<p>رنگ</p>
<div class="swatches">
{[['', 'سپیا', '#fbf6ea', '#bf3f2a'], ['teal', 'فیروزی', '#e2f0ee', '#0b4f6c'], ['lapis', 'نیلگوں', '#e6ebf8', '#1d3b8b'],
@ -193,7 +189,6 @@ import { siteUrl } from '../lib/site-url';
panel.querySelectorAll('[data-font]').forEach((b) => b.setAttribute('aria-pressed', String(b.dataset.font === on.font)));
weight.value = root.style.getPropertyValue('--naskh-weight') || '400';
weight.disabled = on.font === 'nastaliq'; // Nastaliq comes in regular and bold only
size.value = parseInt(root.style.getPropertyValue('--text-size')) || '100';
panel.querySelectorAll('[data-palette]').forEach((b) => b.setAttribute('aria-pressed', String(b.dataset.palette === on.palette)));
panel.querySelectorAll('[data-theme-pick]').forEach((b) => b.setAttribute('aria-pressed', String(b.dataset.themePick === on.theme)));
panel.querySelectorAll('[data-digits]').forEach((b) => b.setAttribute('aria-pressed', String(b.dataset.digits === (root.dataset.digits ?? ''))));
@ -203,18 +198,9 @@ import { siteUrl } from '../lib/site-url';
if (weight.value === '400') root.style.removeProperty('--naskh-weight'); else root.style.setProperty('--naskh-weight', weight.value);
store('divan-weight', weight.value === '400' ? '' : weight.value);
});
const size = panel.querySelector('[data-size]');
size.addEventListener('input', () => {
if (size.value === '100') root.style.removeProperty('--text-size'); else root.style.setProperty('--text-size', size.value + '%');
store('divan-size', size.value === '100' ? '' : size.value);
});
panel.addEventListener('click', (e) => {
const b = e.target.closest('button'); if (!b) return;
if (b.dataset.font) {
// switching to Nastaliq: a short note that it is for the text (the interface stays Naskh, by design)
if (b.dataset.font === 'nastaliq' && !root.classList.contains('nastaliq')) toast('نستعلیق صرف کلام اور متن پر؛ باقی سائٹ نسخ میں رہتی ہے', 'info');
root.classList.toggle('nastaliq', b.dataset.font === 'nastaliq'); store('divan-font', b.dataset.font);
}
if (b.dataset.font) { root.classList.toggle('nastaliq', b.dataset.font === 'nastaliq'); store('divan-font', b.dataset.font); }
if (b.dataset.palette != null) { if (b.dataset.palette) root.dataset.palette = b.dataset.palette; else delete root.dataset.palette; store('divan-palette', b.dataset.palette); }
if (b.dataset.digits != null) {
// numerals: a cookie, so the server sends pages with them; switching back to Eastern reloads the page

View File

@ -114,7 +114,7 @@ import TagsBox from '../components/TagsBox.astro';
{page.type === 'poet' && (
<>
<h1 class="lit" data-readable>{page.poet.name}</h1>
<h1 data-readable>{page.poet.name}</h1>
<div class="center"><button type="button" class="save" data-save={JSON.stringify({ kind: 'poet', poetId })} aria-pressed={String(!!saved.poet)} title="یہ شاعر محفوظ کریں">{label(saved.poet)}</button><button type="button" class="icon-btn small" data-reading-toggle title="مطالعے کا انداز: صرف متن" aria-label="مطالعے کا انداز"><Icon name="dict" size={17} /></button>{arrange && <> <form method="post" action={`/mod/order/${page.category.id}`} class="inline-form"><button class="mod-edit-btn"><Icon name="arrange" size={17} /> ترتیب دیں</button></form>
<a class="icon-btn small" href={`/mod/order/${page.category.id}`} title="ترتیب کا تاریخچہ" aria-label="ترتیب کا تاریخچہ"><Icon name="history" size={17} /></a></>}{tagCan && <> <form method="post" action={`/mod/tags/${tagTarget}`} class="inline-form"><button class="mod-edit-btn"><Icon name="tag" size={17} /> ٹیگ</button></form></>}{catCan.poet && <> <form method="post" action={`/mod/details/poet/${poetId}`} class="inline-form"><button class="mod-edit-btn"><Icon name="edit" size={17} /> تفصیل</button></form></>}</div>
<p class="muted">{years(page.poet)}</p>
@ -123,7 +123,7 @@ import TagsBox from '../components/TagsBox.astro';
)}
{page.type === 'category' && (
<>
<h1 class="lit" data-readable>{page.category.title}</h1>
<h1 data-readable>{page.category.title}</h1>
<div class="center"><button type="button" class="save" data-save={JSON.stringify({ kind: 'category', categoryId: page.category.id })} aria-pressed={String(!!saved.category)} title="یہ کتاب یا باب محفوظ کریں">{label(saved.category)}</button><button type="button" class="icon-btn small" data-reading-toggle title="مطالعے کا انداز: صرف متن" aria-label="مطالعے کا انداز"><Icon name="dict" size={17} /></button>{arrange && <> <form method="post" action={`/mod/order/${page.category.id}`} class="inline-form"><button class="mod-edit-btn"><Icon name="arrange" size={17} /> ترتیب دیں</button></form>
<a class="icon-btn small" href={`/mod/order/${page.category.id}`} title="ترتیب کا تاریخچہ" aria-label="ترتیب کا تاریخچہ"><Icon name="history" size={17} /></a></>}{tagCan && <> <form method="post" action={`/mod/tags/${tagTarget}`} class="inline-form"><button class="mod-edit-btn"><Icon name="tag" size={17} /> ٹیگ</button></form></>}{catCan.book && <> <form method="post" action={`/mod/details/book/${page.category.id}`} class="inline-form"><button class="mod-edit-btn"><Icon name="edit" size={17} /> عنوان</button></form></>}</div>
</>
@ -148,7 +148,7 @@ import TagsBox from '../components/TagsBox.astro';
{page.type === 'poem' && (
<>
<article class="work" data-readable>
<h1 class="lit"><Seg s={show(page.poem.title)} /></h1>
<h1><Seg s={show(page.poem.title)} /></h1>
<p class="byline">{page.poet.nickname}</p>
{re && (
<p class="hl-note muted">

View File

@ -23,7 +23,7 @@ import Icon from '../../components/Icon.astro';
<Base title={`${b.title} · ${b.poet}`} author={b.poet} ogType="book" description={`${b.title}: ${b.poet}${b.coauthors.length ? '، ' + b.coauthors.map((c: any) => c.name).join('، ') : ''} کی کتاب، ${KIND[b.kind]} میں`}
jsonld={{ '@context': 'https://schema.org', '@type': 'Book', name: b.title, inLanguage: 'ur', author: [b.poet, ...b.coauthors.map((c: any) => c.name)].map((name) => ({ '@type': 'Person', name })) }}>
<nav class="crumbs"><a href={b.poet_url}>{b.poet}</a> » <a href={`${b.poet_url}/ebooks?kind=${b.kind}`}>ای بکس</a></nav>
<h1 class="lit">{b.title}</h1>
<h1>{b.title}</h1>
{!b.published && <p class="form-error center">یہ کتاب ابھی جائزے میں ہے؛ صرف موڈریٹر دیکھ سکتے ہیں۔</p>}
<p class="center muted">
{KIND[b.kind]}{mb && <> · {mb}</>}{b.source && <> · ماخذ: {b.source}</>}{b.licence && <> · {b.licence}</>}

View File

@ -65,13 +65,7 @@
* { box-sizing: border-box; }
/* Naskh's weight from the display settings (400 by default; heavier reads better on small screens) */
:root:not(.nastaliq) body { font-weight: var(--naskh-weight, 400); }
/* text size from the display settings: everything is in rem, so the whole page scales (90%-150%) */
html { font-size: var(--text-size, 100%); }
body { margin: 0; background: var(--surface-page); color: var(--text); font-family: var(--font-ui); line-height: 1.9; }
/* The rule: the interface (menus, buttons, forms, paths, footers, admin and moderation) is always Naskh, compact and
calm; the reading font (Naskh or Nastaliq, the reader's choice) is only for the literature: verses and prose, work,
book and poet titles, contents lists, intros, excerpts, the editor and its preview. */
.lit, .poem, .preview, .snippet, .intro, .toc, .lib-couplet, .ebook-text, .dv-editor, .masthead-text, .radif-head { font-family: var(--font); }
body { margin: 0; background: var(--surface-page); color: var(--text); font-family: var(--font); line-height: 1.9; }
:where(a) { color: var(--link); text-decoration: none; }
:where(a):hover { color: var(--active); }
.wrap { max-width: 960px; margin: 0 auto; padding: 0 16px; }
@ -115,8 +109,6 @@ body { margin: 0; background: var(--surface-page); color: var(--text); font-fami
main { padding: 16px 0 48px; }
h1, h2 { line-height: 1.6; margin: .2em 0 .4em; font-weight: 700; text-align: center; color: var(--heading); }
h1 { font-size: clamp(1.3rem, 5vw, var(--fs-2xl)); }
/* Nastaliq titles: its tall letters (ک، گ، ط) and deep descents need room, or they reach into the path line above */
:root.nastaliq h1.lit { line-height: 2.4; margin-top: .6em; }
h1::after { content: ''; display: block; width: 140px; height: 2px; background: var(--brand); margin: 8px auto 0; }
/* Ganjoor's gold pill headings and links (.century / .part-title-block) */
@ -191,7 +183,7 @@ h1::after { content: ''; display: block; width: 140px; height: 2px; background:
.couplet p { margin: 0; width: fit-content; max-width: 100%; justify-self: end; text-align: center; }
.couplet[data-mark]::before { content: attr(data-mark); grid-column: 1 / -1; justify-self: center; font-size: .72rem; line-height: 1.6; color: var(--brand); border: 1px solid var(--line); border-radius: 999px; padding: 0 10px; margin-bottom: 2px; }
.takhallus { color: var(--brand); }
.radif { text-align: center; margin-top: 8px; }
.radif { text-align: center; margin-top: -6px; }
.radif-head { text-align: center; font-size: 1.05rem; color: var(--brand); margin: 22px 0 4px; }
.couplet p + p { justify-self: start; }
.couplet::after { content: '✤'; grid-column: 1 / -1; text-align: center; color: var(--brand); font-size: .72rem; opacity: .75; line-height: 1.2; }
@ -248,11 +240,10 @@ h1 + .muted { text-align: center; margin-top: 0; }
.search-form { order: 3; flex-basis: 100%; }
}
.site-header .kb:not([hidden]) { display: block; padding-bottom: 10px; } /* not the header's flex row */
.kb { width: 100%; max-width: 640px; margin-inline: auto; box-sizing: border-box; } /* one keyboard everywhere (header, under a field, in a dialog, docked): */
.kb div { display: flex; justify-content: center; gap: 4px; margin-top: 4px; } /* rows never wrap; a letter is a tenth of the row, */
.kb button { flex: 0 1 calc((100% - 36px) / 10); min-width: 0; padding: 3px 0; font-size: var(--fs-lg); background: var(--surface-raised); border-radius: var(--r-sm); }
.kb .fn { flex-basis: calc((100% - 36px) / 10 * 1.5); background: var(--surface-sunken); } /* shift and delete a bit wider, */
.kb .wide { flex: 1 1 auto; } /* and the space bar takes the rest of its row, as on a phone */
.kb div { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; margin-top: 4px; }
.kb button { font-size: var(--fs-lg); min-width: 2.4em; padding: 2px 6px; background: var(--surface-raised); border-radius: var(--r-sm); }
.kb .wide { min-width: 12em; }
.kb .fn { min-width: 3.4em; background: var(--surface-sunken); }
/* the content editor's keyboard: docked at the bottom of the window; the page keeps the writing line above it */
.kb.kb-float { position: fixed; z-index: 40; inset-inline: 0; bottom: 0; margin: 0 auto; max-width: min(720px, 100vw); padding: 6px 10px 12px;
background: var(--surface-raised); border: 1.5px solid var(--border); border-bottom: 0; border-radius: var(--r-lg) var(--r-lg) 0 0;
@ -580,9 +571,8 @@ h1 + .muted { text-align: center; margin-top: 0; }
.display-panel p { margin: 6px 0 4px; color: var(--text-muted); font-size: .8rem; }
.display-panel .seg { display: flex; gap: 4px; }
.display-panel button { flex: 1; gap: 4px; padding: 2px 6px; border-radius: var(--r-md); }
.display-panel .weight { display: grid; grid-template-columns: 6.5em 1fr; align-items: center; gap: 8px; margin: 6px 0 2px; font-size: .8rem; color: var(--text-muted); } /* the same label width, so both sliders are the same length */
.display-panel .weight span { white-space: nowrap; }
.display-panel .weight input { width: 100%; min-width: 0; margin: 0; accent-color: var(--action); }
.display-panel .weight { display: flex; align-items: center; gap: 8px; margin: 6px 0 2px; font-size: .8rem; color: var(--text-muted); }
.display-panel .weight input { flex: 1; accent-color: var(--action); }
.display-panel .weight:has(input:disabled) { opacity: .5; }
.display-panel .f-nastaliq { font-family: 'Noto Nastaliq Urdu', serif; line-height: 2.2; }
.display-panel .swatches { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; }
@ -686,7 +676,6 @@ h1 + .muted { text-align: center; margin-top: 0; }
font: var(--fs-sm)/1.8 var(--font-ui); animation: toast-in .25s ease-out; }
.toast::before { content: '✓ '; color: var(--ok); font-weight: 700; }
.toast.error::before { content: '! '; color: var(--danger); }
.toast.info::before { content: 'ⓘ '; color: var(--accent); }
.toast.out { animation: toast-out .3s ease-in forwards; }
@keyframes toast-in { from { opacity: 0; transform: translateY(14px); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(14px); } }
@ -756,6 +745,7 @@ p, li { text-wrap: pretty; }
.note-field .in-box { top: 20px; } /* at the first line of the box, not its middle */
.note-field textarea { padding-left: 80px; } /* the buttons sit on the left whatever the note's language (the box follows what is typed) */
.note-box .kb { padding: 0 0 10px; }
.note-box .kb button { min-width: 2em; font-size: 1rem; }
.note-others { list-style: none; margin: 0 0 10px; padding: 8px 0 0; border-top: 1px dashed var(--line); }
.note-others button { all: unset; display: block; cursor: pointer; font-size: var(--fs-sm); color: var(--text-muted); padding: 2px 0; }
.note-others button:hover { color: var(--active); }