ganjoorandroid/design/components/bundle.css
Claude 64a67ddbbd
Set each couplet in a dim rounded card, on every screen size
Each line of verse now sits in its own soft card (surface-container-high,
12dp corners), so the eye finds where one couplet ends and the next
begins, and the couplet's chevron, actions and summary visibly belong to
it. On OLED black that step is all but black, so the card takes the next
one up there. Prose stays bare: a paragraph in a box reads as a quotation.

Text keeps at least 6:1 on the card in every theme. The phone layout is
otherwise unchanged.

Updates the Couplet notes, the stylesheet and wireframes 4-8, and adds
wireframe 9 for the phone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RhmDdrN5hgWrgRcFLAMsV6
2026-10-07 16:04:08 +00:00

160 lines
14 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Ganjoor — static renditions of the app's Compose components. Values come from tokens.css. */
.gj { font-family: var(--font-naskh); color: var(--on-surface); background: var(--surface); }
.gj[lang="en"] { font-family: var(--font-libron); }
.gj *, .gj *::before, .gj *::after { box-sizing: border-box; }
.gj-icon { width: var(--icon); height: var(--icon); fill: currentColor; flex: none; display: block; }
.gj-icon-btn { width: var(--touch); height: var(--touch); border: 0; background: none; color: var(--on-surface-variant); border-radius: var(--radius-full); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; }
.gj-icon-btn:hover { background: color-mix(in srgb, var(--on-surface-variant) 8%, transparent); }
.gj-icon-btn:focus-visible, .gj-text-btn:focus-visible, .gj-chip:focus-visible, .gj-card:focus-visible, .gj-row:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
/* Top app bar: 64px, surface, title-large; nav icon on-surface, actions on-surface-variant. */
.gj-topbar { height: 64px; display: flex; align-items: center; gap: var(--space-4); padding: 0 var(--space-4); background: var(--surface); }
.gj-topbar .gj-nav { color: var(--on-surface); }
.gj-topbar-title { flex: 1; min-width: 0; font-size: 22px; line-height: 28px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-inline-start: var(--space-4); }
.gj-topbar-actions { display: flex; }
.gj-topbar .gj-on { color: var(--primary); }
/* Text button: primary label-large, pill, 40px. */
.gj-text-btn { height: 40px; padding: 0 12px; border: 0; background: none; border-radius: var(--radius-full); color: var(--primary); font: 500 14px/20px var(--font-naskh); letter-spacing: 0.1px; display: inline-flex; align-items: center; gap: var(--space-4); cursor: pointer; }
.gj[lang="en"] .gj-text-btn { font-family: var(--font-libron); }
.gj-text-btn .gj-icon { width: var(--icon-inline); height: var(--icon-inline); }
.gj-text-btn.is-neutral { color: var(--on-surface); }
/* Breadcrumbs: title-medium; ancestors primary and tappable, current on-surface, » separators muted. */
.gj-crumbs { display: flex; flex-wrap: wrap; align-items: center; font-size: 16px; line-height: 24px; font-weight: 500; }
.gj-crumbs a { color: var(--primary); text-decoration: none; cursor: pointer; }
.gj-crumbs .gj-sep { color: var(--on-surface-variant); white-space: pre; }
.gj-crumbs .gj-here { color: var(--on-surface); }
.gj-metre { font-size: 12px; line-height: 16px; letter-spacing: .4px; color: var(--on-surface-variant); }
/* Couplet: two hemistichs stacked; first to the start, second to the end. */
.gj-couplet { margin: var(--space-4) 0; padding: var(--space-8) var(--space-12); border-radius: var(--radius-md); background: var(--surface-container-high); }
.gj-couplet.is-prose { margin: 0; padding: var(--space-6) 0; background: none; }
.gj-verse { font-family: var(--font-naskh); font-size: 22px; line-height: 1.8; color: var(--on-surface); margin: 0; }
.gj-couplet.is-nastaliq .gj-verse { font-family: var(--font-nastaliq); line-height: 2.4; }
.gj-verse.is-first { text-align: start; }
.gj-verse.is-second { text-align: end; }
.gj-verse.is-centered { text-align: center; }
.gj-verse.is-prose { text-align: justify; }
.gj-couplet-summary { font-size: 12px; line-height: 16px; letter-spacing: .4px; color: var(--on-surface-variant); padding-top: var(--space-4); }
.gj-couplet-toggle { display: flex; justify-content: flex-end; }
.gj-couplet-toggle .gj-icon-btn { width: var(--touch-compact); height: var(--touch-compact); }
.gj-couplet-toggle .gj-icon { width: var(--icon-small); height: var(--icon-small); }
.gj-actions { display: flex; flex-wrap: wrap; gap: var(--space-8); }
/* Filter chips: 32px, radius-sm; selected = secondary-container with a check. */
.gj-chips { display: flex; flex-wrap: wrap; gap: var(--space-8); }
.gj-chip { height: 32px; padding: 0 16px; border-radius: var(--radius-sm); border: 1px solid var(--outline); background: transparent; color: var(--on-surface-variant); font: 500 14px/20px var(--font-naskh); letter-spacing: .1px; display: inline-flex; align-items: center; gap: var(--space-8); cursor: pointer; }
.gj[lang="en"] .gj-chip { font-family: var(--font-libron); }
.gj-chip[aria-pressed="true"] { background: var(--secondary-container); color: var(--on-secondary-container); border-color: transparent; padding-inline-start: 8px; }
.gj-chip .gj-icon { width: var(--icon-inline); height: var(--icon-inline); }
/* Poet portrait disc: secondary-container with the initial underneath the photo. */
.gj-portrait { border-radius: var(--radius-full); background: var(--secondary-container); color: var(--on-secondary-container); display: flex; align-items: center; justify-content: center; overflow: hidden; flex: none; position: relative; }
.gj-portrait img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.gj-portrait.is-row { width: var(--avatar-row); height: var(--avatar-row); font-size: 16px; }
.gj-portrait.is-card { width: var(--avatar-card); height: var(--avatar-card); font-size: 28px; line-height: 36px; }
/* Poet card: filled Card, radius-md, surface-container-highest, 12 padding, 8 gap. */
.gj-poet-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--poet-grid-min), 1fr)); gap: var(--space-12); }
.gj-card { background: var(--surface-container-highest); color: var(--on-surface); border-radius: var(--radius-md); padding: var(--space-12); display: flex; flex-direction: column; align-items: center; gap: var(--space-8); cursor: pointer; }
.gj-name { font-size: 16px; line-height: 24px; font-weight: 500; letter-spacing: .15px; text-align: center; display: flex; align-items: center; gap: var(--space-4); }
.gj-pin { width: var(--icon-pin); height: var(--icon-pin); color: var(--primary); fill: currentColor; flex: none; }
/* List row: Material ListItem, 16 side padding, 56–72 tall. */
.gj-row { display: flex; align-items: center; gap: var(--space-16); min-height: 72px; padding: var(--space-8) var(--space-16); background: var(--surface); cursor: pointer; }
.gj-row-text { flex: 1; min-width: 0; }
.gj-row-trailing { display: flex; align-items: center; gap: var(--space-4); }
.gj-row-support { font-size: 14px; line-height: 20px; letter-spacing: .25px; color: var(--on-surface-variant); }
/* Download state, all in a 48px box so ticks and arrows line up. */
.gj-dl { width: var(--touch); height: var(--touch); display: inline-flex; align-items: center; justify-content: center; }
.gj-dl.is-saved { color: var(--downloaded); }
.gj-dl.is-idle { color: var(--on-surface-variant); }
.gj-ring { width: var(--icon-inline); height: var(--icon-inline); border-radius: 50%; border: var(--space-2) solid var(--surface-container-highest); border-top-color: var(--primary); }
/* Settings sheet pieces. */
.gj-sheet { background: var(--surface-container-low); border-radius: var(--radius-xl) var(--radius-xl) 0 0; padding: var(--space-8) var(--space-20) var(--space-32); display: flex; flex-direction: column; gap: var(--space-8); }
.gj-handle { width: 32px; height: 4px; border-radius: var(--radius-full); background: var(--on-surface-variant); opacity: .4; margin: var(--space-8) auto var(--space-8); }
.gj-label { font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: .1px; color: var(--primary); padding-top: var(--space-12); }
.gj-toggle { display: flex; align-items: center; gap: var(--space-16); padding-top: var(--space-12); }
.gj-toggle-text { flex: 1; }
.gj-toggle-title { font-size: 16px; line-height: 24px; color: var(--on-surface); }
.gj-toggle-note { font-size: 12px; line-height: 16px; letter-spacing: .4px; color: var(--on-surface-variant); }
.gj-switch { width: 52px; height: 32px; border-radius: var(--radius-full); border: 2px solid var(--outline); background: var(--surface-container-highest); position: relative; flex: none; cursor: pointer; padding: 0; }
.gj-switch::after { content: ""; position: absolute; top: 50%; inset-inline-start: 6px; width: 16px; height: 16px; margin-top: -8px; border-radius: 50%; background: var(--outline); }
.gj-switch[aria-checked="true"] { background: var(--primary); border-color: var(--primary); }
.gj-switch[aria-checked="true"]::after { inset-inline-start: auto; inset-inline-end: 2px; width: 24px; height: 24px; margin-top: -12px; background: var(--on-primary); }
/* Bottom search bar: tonal surface, outlined field. */
.gj-searchbar { background: var(--surface-tonal-3); padding: var(--space-8) var(--space-12); }
.gj-field { height: 56px; border: 1px solid var(--outline); border-radius: var(--radius-xs); display: flex; align-items: center; gap: var(--space-16); padding: 0 var(--space-12); color: var(--on-surface-variant); font-size: 16px; line-height: 24px; letter-spacing: .5px; }
.gj-search-poems { display: flex; align-items: center; gap: var(--space-16); min-height: 56px; padding: 0 var(--space-16); color: var(--on-surface); }
.gj-search-poems .gj-icon { color: var(--primary); }
.gj-divider { height: 1px; background: var(--outline-variant); border: 0; margin: 0; }
.gj-ai-note { font-size: 11px; line-height: 16px; font-weight: 500; letter-spacing: .5px; color: var(--primary); padding-top: var(--space-12); }
.gj-summary { font-size: 14px; line-height: 20px; letter-spacing: .25px; color: var(--on-surface-variant); }
/* ── Large screens: ColumnBrowser (tablets, unfolded foldables; width ≥ 600) ──
Column browser in RTL: poets rail on the far right, then books, then chapters / poems,
and the open poem fills what is left on the left. */
.gj-ts { display: flex; height: 100%; overflow: hidden; background: var(--surface); }
.gj-ts-home { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.gj-ts.is-split .gj-ts-home { display: none; }
.gj-ts-scroll { overflow-y: auto; min-height: 0; overscroll-behavior: contain; }
.gj-ts-cols { display: none; flex: none; height: 100%; }
.gj-ts.is-split .gj-ts-cols { display: flex; }
.gj-ts-col { flex: none; width: 224px; display: flex; flex-direction: column; min-height: 0; border-inline-end: 1px solid var(--outline-variant); background: var(--surface-container-low); transition: width 300ms cubic-bezier(.2,0,0,1); }
.gj-ts-col.is-new { animation: gj-ts-in 400ms cubic-bezier(.05,.7,.1,1) both; }
/* Columns narrow as you go deeper: the newest list is widest, older ones give their room to the poem. */
.gj-ts-col[data-dist="1"] { width: 168px; }
.gj-ts-col[data-dist="2"] { width: 132px; }
.gj-ts-col[data-dist="1"] .gj-ts-item, .gj-ts-col[data-dist="2"] .gj-ts-item { font-size: 14px; line-height: 20px; padding: var(--space-8); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.gj-ts-col[data-dist="1"] .gj-ts-item small, .gj-ts-col[data-dist="2"] .gj-ts-item small, .gj-ts-col[data-dist="1"] .gj-ts-item::after, .gj-ts-col[data-dist="2"] .gj-ts-item::after { display: none; }
.gj-ts-col[data-dist="1"] .gj-ts-colhead, .gj-ts-col[data-dist="2"] .gj-ts-colhead { padding: 0 var(--space-8); }
.gj-ts-col[data-dist="1"] .gj-ts-colhead b, .gj-ts-col[data-dist="2"] .gj-ts-colhead b { font-size: 14px; line-height: 20px; }
.gj-ts-col.is-rail { width: 96px; background: var(--surface-container); }
.gj-ts.is-deep .gj-ts-col.is-rail { width: 80px; }
.gj-ts.is-deep .gj-ts-poet .gj-portrait { width: 44px; height: 44px; font-size: 18px; }
.gj-ts-poet { overflow-wrap: anywhere; }
@keyframes gj-ts-in { from { opacity: 0; transform: translateX(-32px); } }
.gj-ts-col.is-rail.is-arriving { animation-name: gj-ts-rail; }
@keyframes gj-ts-rail { from { width: 100vw; } }
.gj-ts-colhead { flex: none; min-height: 56px; display: flex; flex-direction: column; justify-content: center; padding: 0 var(--space-16); border-bottom: 1px solid var(--outline-variant); }
.gj-ts-colhead small { color: var(--on-surface-variant); font: 500 11px/16px var(--font-naskh); letter-spacing: .5px; }
.gj-ts-colhead b { color: var(--on-surface); font: 500 16px/24px var(--font-naskh); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.gj-ts-list { padding: var(--space-8); flex: 1; }
/* Poets rail: portrait with the name under it. */
.gj-ts-poet { display: flex; flex-direction: column; align-items: center; gap: var(--space-4); width: 100%; padding: var(--space-8) var(--space-4); border: 0; background: none; border-radius: var(--radius-md); color: var(--on-surface); font: 500 12px/16px var(--font-naskh); letter-spacing: .5px; text-align: center; cursor: pointer; }
.gj-ts-poet .gj-portrait { width: 56px; height: 56px; font-size: 22px; }
.gj-ts-poet[aria-current="true"] { background: var(--secondary-container); color: var(--on-secondary-container); }
.gj-ts-poet[aria-current="true"] .gj-portrait { outline: 2px solid var(--primary); outline-offset: 2px; }
/* Book / chapter / poem rows. */
.gj-ts-item { display: block; width: 100%; min-height: 48px; padding: var(--space-8) var(--space-12); border: 0; background: none; color: var(--on-surface); font: 400 16px/24px var(--font-naskh); text-align: start; cursor: pointer; border-radius: var(--radius-md); }
.gj-ts-item small { display: block; color: var(--on-surface-variant); font-size: 12px; line-height: 16px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.gj-ts-item:hover, .gj-ts-poet:hover { background: color-mix(in srgb, var(--on-surface) 6%, transparent); }
.gj-ts-item[aria-current="true"] { background: var(--secondary-container); color: var(--on-secondary-container); }
.gj-ts-item[aria-current="true"] small { color: var(--on-secondary-container); }
.gj-ts-item.has-kids::after { content: "‹"; float: inline-end; color: var(--on-surface-variant); }
/* Focus mode: the columns fold away and the poem takes the whole width, still centred. */
.gj-ts.is-focus .gj-ts-cols { display: none; }
.gj-ts-toggle[aria-pressed="false"] { color: var(--primary); }
/* The open work. */
.gj-ts-main { flex: 1; min-width: 0; display: flex; flex-direction: column; animation: gj-ts-in 400ms cubic-bezier(.05,.7,.1,1) both; }
.gj-ts-content { flex: 1; padding: var(--space-8) var(--space-32) var(--space-32); }
.gj-ts-measure { max-width: 680px; margin-inline: auto; }
.gj-ts-main { container-type: inline-size; }
/* Hemistichs side by side only when the poem column has room; otherwise they stack as on a phone. */
.gj-ts .gj-couplet.is-wide .gj-verse.is-first { text-align: start; }
.gj-ts .gj-couplet.is-wide .gj-verse.is-second { text-align: end; }
@container (min-width: 640px) {
.gj-ts .gj-couplet.is-wide { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--space-32); align-items: baseline; }
}
.gj-ts-books { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--space-12); margin-top: var(--space-16); }
.gj-ts-books .gj-card { align-items: flex-start; text-align: start; }