Setări pentru lectură

Personalizează textul pentru o lectură mai confortabilă.

Dimensiunea textului 20-48 px
Spațiul dintre rânduri 2,10
@import url(‘https://fonts.googleapis.com/css2?family=Playwrite+RO:[email protected]&display=swap’); /* ========================================================== BIBLIOTECA MEA READER ========================================================== */ .bm-reader, .bm-reader * { box-sizing: border-box; } /* ========================================================== CONTAINER PRINCIPAL ========================================================== */ .bm-reader { –bm-ink: #111111; –bm-title: #111111; –bm-muted: #111111; –bm-soft-text: #111111; –bm-border: #e5e9f0; –bm-border-strong: #d7ddea; –bm-panel: #ffffff; –bm-soft: #f8f9fb; –bm-soft-blue: #f1f5ff; –bm-soft-red: #fff1f2; –bm-accent: #ef4452; –bm-accent-dark: #dd3341; –bm-navy: #12246b; –bm-focus: #2657d8; width: min(calc(100% – 32px), 1120px); /* Panoul rămâne centrat pe telefon, tabletă, desktop și TV. */ max-width: 1120px; margin: 16px auto; overflow: hidden; border: 1px solid var(–bm-border); border-radius: 16px; background: var(–bm-panel); color: var(–bm-ink); font-family: inherit; box-shadow: 0 1px 2px rgba(16, 24, 40, .025), 0 5px 18px rgba(16, 24, 40, .035); } .bm-reader button, .bm-reader input { font: inherit; } .bm-reader button { -webkit-tap-highlight-color: transparent; } /* ========================================================== HEADER ========================================================== */ .bm-reader__header { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 14px 9px; } .bm-reader__heading { display: flex; align-items: center; gap: 9px; min-width: 0; } .bm-reader__heading-icon { width: 32px; height: 32px; flex: 0 0 32px; display: inline-flex; align-items: center; justify-content: center; border-radius: 10px; background: var(–bm-soft-red); color: var(–bm-accent); } .bm-reader__heading-icon svg { width: 16px; height: 16px; } .bm-reader__heading-copy { min-width: 0; } .bm-reader__title { margin: 0 0 2px !important; padding: 0 !important; color: #111111 !important; font-size: 18px !important; line-height: 1.25 !important; font-weight: 600 !important; letter-spacing: -.015em; } .bm-reader__description { margin: 0 !important; padding: 0 !important; color: #111111 !important; font-size: 14px !important; line-height: 1.45 !important; font-weight: 400 !important; } /* ========================================================== BUTON MAI MULTE OPȚIUNI ========================================================== */ .bm-reader__advanced-toggle { appearance: none; min-height: 32px; display: inline-flex; align-items: center; justify-content: center; gap: 7px; flex: 0 0 auto; margin: 0; padding: 0 12px; border: 1px solid #dedede; border-radius: 999px; background: #ffffff; color: #111111 !important; font-size: 15px; line-height: 1.2; font-weight: 500; cursor: pointer; transition: background-color .16s ease, border-color .16s ease, transform .16s ease; } .bm-reader__advanced-toggle:hover { background: #f7f7f7; border-color: #cfcfcf; } .bm-reader__advanced-toggle:active { transform: scale(.985); } .bm-reader__advanced-arrow { width: 7px; height: 7px; border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor; transform: rotate(45deg) translateY(-2px); transition: transform .2s ease; } .bm-reader__advanced-toggle[aria-expanded=”true”] .bm-reader__advanced-arrow { transform: rotate(225deg) translate(-1px, -1px); } /* ========================================================== ZONA PRINCIPALĂ ========================================================== */ .bm-reader__primary { display: grid; grid-template-columns: minmax(180px, .9fr) minmax(250px, 1.25fr) minmax(300px, 1.35fr); gap: 7px; padding: 0 14px 13px; } .bm-reader__primary-card { min-width: 0; min-height: 72px; display: flex; flex-direction: column; justify-content: center; padding: 9px 10px; border: 1px solid var(–bm-border); border-radius: 12px; background: #ffffff; } .bm-reader__control-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; } .bm-reader__control-title { color: #111111 !important; font-size: 13px; line-height: 1.3; font-weight: 600; } .bm-reader__control-hint, .bm-reader__range-value { color: #111111 !important; font-size: 12px; line-height: 1.2; font-weight: 500; } /* ========================================================== FONT SIZE STEPPER ========================================================== */ .bm-reader__stepper { height: 32px; display: grid; grid-template-columns: 36px 1fr 36px; overflow: hidden; border: 1px solid var(–bm-border-strong); border-radius: 9px; background: #ffffff; } .bm-reader__stepper button { appearance: none; margin: 0; padding: 0; border: 0; background: transparent; color: #111111; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color .15s ease; } .bm-reader__stepper button:hover { background: var(–bm-soft); } .bm-reader__stepper button + button { border-left: 1px solid var(–bm-border); } .bm-reader__stepper-value { font-size: 14px !important; font-weight: 600 !important; } /* ========================================================== LINE HEIGHT ========================================================== */ .bm-reader__range-wrap { height: 32px; display: flex; align-items: center; gap: 8px; padding: 0 9px; border: 1px solid var(–bm-border-strong); border-radius: 9px; background: #ffffff; } .bm-reader__range-icon { display: inline-flex; color: #7b86a0; } .bm-reader__range-icon svg { width: 15px; height: 15px; } .bm-reader__range-wrap input[type=”range”] { width: 100%; min-width: 80px; margin: 0; accent-color: var(–bm-accent); cursor: pointer; } /* ========================================================== ACȚIUNI RAPIDE ========================================================== */ .bm-reader__quick-actions { min-width: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; } .bm-reader__quick { appearance: none; min-width: 0; min-height: 72px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; margin: 0; padding: 7px 6px; border: 1px solid var(–bm-border); border-radius: 12px; background: #ffffff; color: #111111 !important; font-size: 16px; line-height: 1.3; font-weight: 500; text-align: center; cursor: pointer; transition: background-color .15s ease, border-color .15s ease, color .15s ease, transform .15s ease; } .bm-reader__quick:hover { background: var(–bm-soft); } .bm-reader__quick:active { transform: scale(.985); } .bm-reader__quick[aria-pressed=”true”] { border-color: var(–bm-navy); background: var(–bm-navy); color: #ffffff !important; } .bm-reader__quick–reset { color: #111111 !important; } .bm-reader__quick–reset:hover { background: #fff7f8; border-color: #f0c6ca; } .bm-reader__quick-icon { height: 17px; display: inline-flex; align-items: center; justify-content: center; } .bm-reader__quick-icon–syllable { font-size: 13px; font-weight: 700; letter-spacing: -.02em; } .bm-reader__quick-icon–bionic { font-size: 18px; font-weight: 700; } /* ========================================================== ADVANCED PANEL ========================================================== */ .bm-reader__advanced { border-top: 1px solid var(–bm-border); background: #fbfcfe; animation: bmReaderOpen .2s ease; } .bm-reader__advanced[hidden] { display: none !important; } .bm-reader__advanced-inner { padding: 14px 14px 15px; } @keyframes bmReaderOpen { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } } /* ========================================================== HEADINGS ADVANCED ========================================================== */ .bm-reader__section-head, .bm-reader__fonts-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; margin-bottom: 9px; } .bm-reader__section-head–tools { margin-bottom: 8px; } .bm-reader__eyebrow { display: block; margin-bottom: 2px; color: var(–bm-accent); font-size: 10px; line-height: 1.3; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; } .bm-reader__section-title { margin: 0 !important; padding: 0 !important; color: #111111 !important; font-size: 17px !important; line-height: 1.3 !important; font-weight: 600 !important; letter-spacing: -.01em; } .bm-reader__section-note { color: #111111 !important; font-size: 9px; line-height: 1.35; white-space: nowrap; } /* ========================================================== DIVIDER ========================================================== */ .bm-reader__divider { height: 1px; margin: 13px 0; background: var(–bm-border); } /* ========================================================== INSTRUMENTE ========================================================== */ .bm-reader__tools-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; } .bm-reader__tool { appearance: none; min-width: 0; min-height: 72px; display: grid; grid-template-columns: 29px minmax(0, 1fr) 27px; align-items: center; gap: 7px; margin: 0; padding: 8px; border: 1px solid var(–bm-border); border-radius: 11px; background: #ffffff; color: #111111 !important; text-align: left; cursor: pointer; transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease; } .bm-reader__tool:hover { background: #fcfdff; border-color: #d9dfeb; } .bm-reader__tool[aria-pressed=”true”] { border-color: #bcc7e4; background: #f7f9ff; } .bm-reader__tool-icon { width: 29px; height: 29px; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; background: var(–bm-soft-blue); color: var(–bm-navy); } .bm-reader__tool-icon svg { width: 16px; height: 16px; } .bm-reader__tool-icon–letters { font-size: 10px; font-weight: 700; letter-spacing: -.03em; } .bm-reader__tool-copy { min-width: 0; display: flex; flex-direction: column; gap: 1px; } .bm-reader__tool-copy strong { color: #111111 !important; font-size: 13px; line-height: 1.3; font-weight: 600; } .bm-reader__tool-copy small { color: #111111 !important; font-size: 11px; line-height: 1.4; font-weight: 400; } /* ========================================================== SWITCH ========================================================== */ .bm-reader__switch { position: relative; width: 26px; height: 15px; flex: 0 0 26px; border-radius: 999px; background: #d9dee8; transition: background-color .18s ease; } .bm-reader__switch::after { content: “”; position: absolute; top: 2px; left: 2px; width: 11px; height: 11px; border-radius: 50%; background: #ffffff; box-shadow: 0 1px 2px rgba(16, 24, 40, .18); transition: transform .18s ease; } .bm-reader__tool[aria-pressed=”true”] .bm-reader__switch { background: var(–bm-navy); } .bm-reader__tool[aria-pressed=”true”] .bm-reader__switch::after { transform: translateX(11px); } /* ========================================================== FONTURI ========================================================== */ .bm-reader__fonts-head { align-items: center; margin-bottom: 8px; } .bm-reader__fonts-aa { width: 31px; height: 31px; display: inline-flex; align-items: center; justify-content: center; border-radius: 9px; background: var(–bm-soft-red); color: var(–bm-accent); font-size: 12px; font-weight: 700; } .bm-reader__font-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 5px; } .bm-reader__font { appearance: none; min-width: 0; min-height: 58px; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px; margin: 0; padding: 7px 8px; border: 1px solid var(–bm-border); border-radius: 10px; background: #ffffff; color: #111111 !important; text-align: left; cursor: pointer; transition: background-color .15s ease, border-color .15s ease, color .15s ease, transform .15s ease; } .bm-reader__font:hover { background: var(–bm-soft); transform: translateY(-1px); } .bm-reader__font.is-active { border-color: var(–bm-navy); background: var(–bm-navy); color: #ffffff !important; } .bm-reader__font strong { color: inherit; font-size: 13px; line-height: 1.3; font-weight: 600; } .bm-reader__font span { color: inherit; opacity: .82; font-size: 12px; line-height: 1.3; } .bm-reader__font[data-bm-font=”lexend”] { font-family: Lexend, Arial, sans-serif; } .bm-reader__font[data-bm-font=”literata”] { font-family: Literata, Georgia, serif; } .bm-reader__font[data-bm-font=”playwrite”] { font-family: “Playwrite RO”, cursive; } /* ========================================================== TEXTUL PAGINII ========================================================== */ [data-bm-reading-content] { –bm-reader-font-size: 34px; –bm-reader-line-height: 2.10; –bm-reader-width: 760px; width: min( 100%, var(–bm-reader-width) ); margin-left: auto; margin-right: auto; font-size: var(–bm-reader-font-size) !important; line-height: var(–bm-reader-line-height) !important; transition: width .2s ease, max-width .2s ease, font-size .2s ease, line-height .2s ease, background-color .2s ease, color .2s ease; } [data-bm-reading-content] p, [data-bm-reading-content] li, [data-bm-reading-content] blockquote { font-size: inherit !important; line-height: inherit !important; } [data-bm-auto-reading-content] { display: flow-root; } [data-bm-auto-reading-content] > :first-child { margin-top: 0; } [data-bm-auto-reading-content] > :last-child { margin-bottom: 0; } /* ========================================================== TEMELE TEXTULUI ========================================================== */ [data-bm-reading-content].bm-reader-theme-light { color: #15171b; background: #ffffff; } [data-bm-reading-content].bm-reader-theme-warm { color: #2a2118; background: #fff8e9; } [data-bm-reading-content].bm-reader-theme-gray { color: #1f2328; background: #f1f3f5; } [data-bm-reading-content].bm-reader-theme-dark { color: #f5f7fa; background: #17191f; } [data-bm-reading-content].bm-reader-theme-warm, [data-bm-reading-content].bm-reader-theme-gray, [data-bm-reading-content].bm-reader-theme-dark { padding: 30px; border-radius: 18px; } [data-bm-reading-content].bm-reader-bold { font-weight: 650; } [data-bm-reading-content].bm-reader-uppercase { text-transform: uppercase; } .bm-reader-bionic { font-weight: 780; } .bm-reader-syllable–1 { color: #d83b47; } .bm-reader-syllable–2 { color: #245bb8; } /* ========================================================== LINIE DE CITIRE ========================================================== */ [data-bm-reading-content].bm-reader-line-enabled p, [data-bm-reading-content].bm-reader-line-enabled li, [data-bm-reading-content].bm-reader-line-enabled blockquote { position: relative; border-radius: 7px; transition: background-color .12s ease; } [data-bm-reading-content].bm-reader-line-enabled .bm-reader-line-active { background: rgba(255, 220, 70, .24); } /* ========================================================== WORDPRESS DIRECT TARGETS ========================================================== */ [data-bm-reading-target] { transition: font-size .18s ease, line-height .18s ease, color .18s ease, background-color .18s ease, max-width .18s ease; } [data-bm-reading-target].bm-reader-line-active { background-image: linear-gradient( rgba(255, 220, 70, .24), rgba(255, 220, 70, .24) ); border-radius: 5px; } /* ========================================================== FOCUS ========================================================== */ .bm-reader button:focus-visible, .bm-reader input:focus-visible { outline: 2px solid var(–bm-focus); outline-offset: 2px; } .bm-reader button:disabled { opacity: .38; cursor: not-allowed; } /* ========================================================== TABLET ========================================================== */ /* TV / ecrane foarte late */ @media (min-width: 1440px) { .bm-reader { width: min(calc(100% – 64px), 1180px); max-width: 1180px; } } @media (max-width: 1050px) { .bm-reader { width: calc( 100% – 28px ); } .bm-reader__primary { grid-template-columns: 1fr 1.35fr; } .bm-reader__quick-actions { grid-column: 1 / -1; } .bm-reader__quick { min-height: 50px; flex-direction: row; } .bm-reader__tools-grid { grid-template-columns: repeat( 2, minmax(0, 1fr) ); } .bm-reader__font-grid { grid-template-columns: repeat( 4, minmax(0, 1fr) ); } } /* ========================================================== MOBILE ========================================================== */ @media (max-width: 700px) { .bm-reader { width: calc( 100% – 20px ); margin: 12px auto; border-radius: 14px; } .bm-reader__header { align-items: flex-start; padding: 11px 12px 8px; } .bm-reader__heading-icon { width: 30px; height: 30px; flex-basis: 30px; } .bm-reader__advanced-toggle { min-height: 31px; } .bm-reader__primary { grid-template-columns: 1fr; padding: 0 12px 12px; gap: 6px; } .bm-reader__primary-card { min-height: 60px; } .bm-reader__quick-actions { grid-column: auto; } .bm-reader__advanced-inner { padding: 12px; } .bm-reader__section-note { display: none; } .bm-reader__font-grid { grid-template-columns: repeat( 3, minmax(0, 1fr) ); } } /* ========================================================== TELEFON MIC ========================================================== */ @media (max-width: 520px) { .bm-reader { width: calc( 100% – 16px ); } .bm-reader__header { flex-direction: column; gap: 9px; } .bm-reader__advanced-toggle { width: 100%; } .bm-reader__quick-actions { grid-template-columns: 1fr; } .bm-reader__quick { min-height: 42px; flex-direction: row; } .bm-reader__tools-grid { grid-template-columns: 1fr; } .bm-reader__font-grid { grid-template-columns: repeat( 2, minmax(0, 1fr) ); } [data-bm-reading-content].bm-reader-theme-warm, [data-bm-reading-content].bm-reader-theme-gray, [data-bm-reading-content].bm-reader-theme-dark { padding: 20px; } } /* ========================================================== TELEFON FOARTE MIC ========================================================== */ @media (max-width: 390px) { .bm-reader { width: calc(100% – 12px); margin: 8px auto; border-radius: 12px; } .bm-reader__advanced-inner { padding: 10px; } } /* ========================================================== REDUCED MOTION ========================================================== */ @media (prefers-reduced-motion: reduce) { .bm-reader *, [data-bm-reading-content] { animation: none !important; transition: none !important; scroll-behavior: auto !important; } } /* ========================================================== TYPOGRAPHY COHERENCE Text mai lizibil și coerent cu blocul introductiv al paginii ========================================================== */ @media (max-width: 700px) { .bm-reader__title { font-size: 17px !important; } .bm-reader__description { font-size: 13px !important; } .bm-reader__advanced-toggle { font-size: 14px; } .bm-reader__quick { font-size: 15px; } .bm-reader__section-title { font-size: 16px !important; } .bm-reader__tool-copy strong { font-size: 13px; } .bm-reader__tool-copy small { font-size: 11px; } } (function () { “use strict”; var STORAGE_KEY = “biblioteca-mea-reader-v7”; var DEFAULTS = { fontSize: 34, lineHeight: 2.10, syllables: false, bionic: false, theme: “system”, width: “medium”, align: “left”, coloredSyllables: false, readingLine: false, boldText: false, uppercase: false, font: “lexend” }; var MIN_FONT_SIZE = 20; var MAX_FONT_SIZE = 48; var FONT_STEP = 2; var WORD_RX = /[A-Za-zĂÂÎȘȚăâîșț]+(?:-[A-Za-zĂÂÎȘȚăâîșț]+)*/g; var WORD_ONLY_RX = /^[A-Za-zĂÂÎȘȚăâîșț]+(?:-[A-Za-zĂÂÎȘȚăâîșț]+)*$/; /* ====================================================== DEFAULTS ====================================================== */ function cloneDefaults() { return Object.assign( {}, DEFAULTS ); } /* ====================================================== LOAD SETTINGS ====================================================== */ function loadSettings() { try { var stored = localStorage.getItem( STORAGE_KEY ); var settings = stored ? Object.assign( {}, DEFAULTS, JSON.parse(stored) ) : cloneDefaults(); if ( settings.font === “noto” || settings.font === “source” || settings.font === “roboto” ) { settings.font = “lexend”; } return settings; } catch (error) { return cloneDefaults(); } } /* ====================================================== SAVE SETTINGS ====================================================== */ function saveSettings(state) { try { localStorage.setItem( STORAGE_KEY, JSON.stringify(state) ); } catch (error) {} } /* ====================================================== DOM POSITION ====================================================== */ function isAfter(reference, node) { return !!( reference.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_FOLLOWING ); } /* ====================================================== EXCLUDED CONTENT ====================================================== */ function isExcludedTextElement(element) { if ( !element || element.nodeType !== 1 ) { return true; } if ( element.closest( “[data-bm-reader]” ) ) { return true; } if ( element.closest( “header, nav, footer, aside” ) ) { return true; } if ( element.closest( “.entry-footer, ” + “.post-footer, ” + “.post-navigation, ” + “.navigation, ” + “.author-box, ” + “.author-bio, ” + “.related-posts, ” + “.related, ” + “.comments-area, ” + “.post-comments, ” + “.share-buttons, ” + “.social-share, ” + “.site-footer, ” + “.wp-block-post-navigation-link, ” + “.wp-block-query, ” + “.wp-block-latest-posts” ) ) { return true; } return false; } /* ====================================================== TEXT LENGTH ====================================================== */ function readableEnough(element) { var text = ( element.textContent || “” ) .replace( /s+/g, ” ” ) .trim(); return text.length >= 2; } /* ====================================================== FIND TEXT AFTER READER PANEL ====================================================== */ function discoverTargets(panel) { var customTarget = panel.getAttribute( “data-bm-target” ); var scope = null; var candidates = []; /* * Permite și selectarea manuală a textului. */ if (customTarget) { try { scope = document.querySelector( customTarget ); } catch (error) { scope = null; } if (scope) { if ( scope.matches && scope.matches( “p, li, blockquote” ) ) { candidates.push( scope ); } candidates = candidates.concat( Array.prototype.slice.call( scope.querySelectorAll( “p, li, blockquote” ) ) ); return candidates.filter( function (element) { return ( !isExcludedTextElement( element ) && readableEnough( element ) ); } ); } } /* * Preferăm articolul în care se află panoul. */ var article = panel.closest( “article” ); if (article) { scope = article; } else { scope = panel.closest( “.entry-content, ” + “.post-content, ” + “.single-content, ” + “.wp-block-post-content, ” + “.elementor-widget-theme-post-content, ” + “main” ) || document.body; } candidates = Array.prototype.slice.call( scope.querySelectorAll( “p, li, blockquote” ) ); candidates = candidates.filter( function (element) { if ( !isAfter( panel, element ) ) { return false; } if ( isExcludedTextElement( element ) ) { return false; } if ( !readableEnough( element ) ) { return false; } if (article) { var ownerArticle = element.closest( “article” ); if ( ownerArticle && ownerArticle !== article ) { return false; } } return true; } ); /* * Fallback pentru unele page buildere. */ if ( !candidates.length ) { candidates = Array.prototype.slice.call( document.querySelectorAll( “p, li, blockquote” ) ) .filter( function (element) { return ( isAfter( panel, element ) && !isExcludedTextElement( element ) && readableEnough( element ) ); } ); } return candidates; } /* ====================================================== TEXT NODES ====================================================== */ function getTextNodes(container) { var nodes = []; var walker = document.createTreeWalker( container, NodeFilter.SHOW_TEXT, { acceptNode: function (node) { if ( !node.nodeValue || !node.nodeValue.trim() ) { return NodeFilter.FILTER_REJECT; } var parent = node.parentElement; if (!parent) { return NodeFilter.FILTER_REJECT; } if ( parent.closest( “script, style, code, pre, textarea, button, a” ) ) { return NodeFilter.FILTER_REJECT; } return NodeFilter.FILTER_ACCEPT; } } ); while ( walker.nextNode() ) { nodes.push( walker.currentNode ); } return nodes; } /* ====================================================== SILABIFICARE ====================================================== */ function syllabifyWord(word) { /* * Silabificarea limbii române nu poate fi rezolvată corect * doar prin regula „taie după fiecare vocală”. * * Pentru formele frecvente din textele pentru copii folosim * un dicționar explicit, iar pentru restul cuvintelor păstrăm * un fallback conservator. * * IMPORTANT: * – alternarea culorilor se resetează pentru fiecare cuvânt; * – formele cu cratimă pot rămâne în aceeași silabă: * mi-ne-n, nu mi-ne-n împărțit ca trei cuvinte. */ var original = word; var lower = word.toLocaleLowerCase(“ro-RO”); var known = { /* Avion cu motor */ “avion”: [“a”, “vi”, “on”], “motor”: [“mo”, “tor”], /* Ia-mă și pe mine-n zbor */ “ia-mă”: [“ia”, “mă”], “mine-n”: [“mi”, “ne-n”], /* Nu te iau, că ești mic */ “nu”: [“nu”], “te”: [“te”], “iau”: [“iau”], “că”: [“că”], “ești”: [“ești”], “mic”: [“mic”], /* Și te cheamă Polonic */ “și”: [“și”], “cheamă”: [“chea”, “mă”], “polonic”: [“po”, “lo”, “nic”], /* Cuvinte monosilabice din poezie */ “cu”: [“cu”], “pe”: [“pe”], “zbor”: [“zbor”] }; function restoreCase(parts) { /* * Păstrează majuscula inițială: * avion -> a-vi-on * Avion -> A-vi-on * Polonic -> Po-lo-nic */ if ( original && original.charAt(0) === original.charAt(0).toLocaleUpperCase(“ro-RO”) && original.charAt(0) !== original.charAt(0).toLocaleLowerCase(“ro-RO”) ) { parts[0] = parts[0].charAt(0).toLocaleUpperCase(“ro-RO”) + parts[0].slice(1); } return parts; } if (known[lower]) { return restoreCase( known[lower].slice() ); } /* * Dacă este o formă cu cratimă pe care nu o cunoaștem, * nu rupem arbitrar cratima. Procesăm fiecare segment și * păstrăm cratima lipită de segmentul următor. */ if (lower.indexOf(“-“) !== -1) { var hyphenParts = original.split(“-“); var result = []; hyphenParts.forEach( function (part, partIndex) { if (!part) { return; } var partSyllables = syllabifyWord(part); partSyllables.forEach( function (syllable, syllableIndex) { if ( partIndex > 0 && syllableIndex === 0 && result.length ) { result[result.length – 1] += “-” + syllable; } else { result.push( syllable ); } } ); } ); return result.length ? result : [original]; } /* * Cuvintele foarte scurte rămân întregi. * Este preferabil să nu colorăm greșit un cuvânt decât * să inventăm o despărțire. */ if (word.length <= 3) { return [word]; } var vowels = "aeiouăâîAEIOUĂÂÎ"; var syllables = []; var current = ""; var i; /* * Fallback simplificat: * găsește nucleele vocalice și mută o consoană dintre * două nuclee la silaba următoare. * * Nu este un dicționar fonetic complet al limbii române, * de aceea excepțiile pedagogice importante rămân în * obiectul `known` de mai sus. */ for ( i = 0; i < word.length; i++ ) { current += word[i]; if ( vowels.indexOf( word[i] ) === -1 ) { continue; } var nextVowelIndex = -1; var j; for ( j = i + 1; j consoana începe de regulă silaba următoare: * mo-tor, po-lo-nic */ syllables.push( current ); current = “”; } else { /* * Pentru grupuri de două sau mai multe consoane, * păstrăm prima consoană în silaba precedentă. * Cazurile care nu urmează această regulă trebuie * adăugate în dicționarul `known`. */ current += word[i + 1] || “”; i++; syllables.push( current ); current = “”; } } if (current) { syllables.push( current ); } /* * Protecție: funcția nu are voie să piardă sau să dubleze * litere. Dacă ceva nu se potrivește, păstrăm cuvântul întreg. */ if ( syllables.join(“”).length !== word.length ) { return [word]; } return syllables.length ? syllables : [word]; } /* ====================================================== PE SILABE ====================================================== */ function applySyllables(container) { getTextNodes( container ) .forEach( function (node) { node.nodeValue = node.nodeValue.replace( WORD_RX, function (word) { if (word.toLocaleLowerCase(“ro-RO”) === “scoate”) { return word.charAt(0) === word.charAt(0).toLocaleUpperCase(“ro-RO”) ? “Scou00E1u00A0u2022u00A0te” : “scou00E1u00A0u2022u00A0te”; } return syllabifyWord(word).join(“-“); } ); } ); } /* ====================================================== SILABE COLORATE ====================================================== */ function applyColoredSyllables(container) { getTextNodes( container ) .forEach( function (node) { var fragment = document.createDocumentFragment(); var pieces = node.nodeValue.split( /([A-Za-zĂÂÎȘȚăâîșț]+(?:-[A-Za-zĂÂÎȘȚăâîșț]+)*)/g ); pieces.forEach( function (piece) { if ( WORD_ONLY_RX.test( piece ) ) { syllabifyWord( piece ) .forEach( function ( syllable, index ) { var span = document.createElement( “span” ); /* Culoarea începe din nou cu roșu la fiecare cuvânt. */ span.className = index % 2 === 0 ? “bm-reader-syllable–1” : “bm-reader-syllable–2”; span.textContent = syllable; fragment.appendChild( span ); } ); } else { fragment.appendChild( document.createTextNode( piece ) ); } } ); if ( node.parentNode ) { node.parentNode.replaceChild( fragment, node ); } } ); } /* ====================================================== BIONIC READING ====================================================== */ function applyBionic(container) { getTextNodes( container ) .forEach( function (node) { var fragment = document.createDocumentFragment(); var pieces = node.nodeValue.split( /([A-Za-zĂÂÎȘȚăâîșț]{3,})/g ); pieces.forEach( function (piece) { if ( /^[A-Za-zĂÂÎȘȚăâîșț]{3,}$/.test( piece ) ) { var boldLength = Math.max( 1, Math.ceil( piece.length * .45 ) ); var strong = document.createElement( “span” ); strong.className = “bm-reader-bionic”; strong.textContent = piece.slice( 0, boldLength ); fragment.appendChild( strong ); fragment.appendChild( document.createTextNode( piece.slice( boldLength ) ) ); } else { fragment.appendChild( document.createTextNode( piece ) ); } } ); if ( node.parentNode ) { node.parentNode.replaceChild( fragment, node ); } } ); } /* ====================================================== FONT FAMILY ====================================================== */ function getFontFamily(font) { var fonts = { roboto: “Roboto, Arial, sans-serif”, lexend: “Lexend, Arial, sans-serif”, atkinson: ‘”Atkinson Hyperlegible”, Arial, sans-serif’, literata: “Literata, Georgia, serif”, playwrite: ‘”Playwrite RO”, cursive’, bionic: “Roboto, Arial, sans-serif” }; return ( fonts[font] || fonts.roboto ); } /* ====================================================== INIT READER ====================================================== */ function initReader( panel, index ) { var advanced = panel.querySelector( “[data-bm-advanced]” ); var advancedToggle = panel.querySelector( “[data-bm-advanced-toggle]” ); var advancedLabel = panel.querySelector( “[data-bm-advanced-label]” ); var fontMinus = panel.querySelector( “[data-bm-font-minus]” ); var fontPlus = panel.querySelector( “[data-bm-font-plus]” ); var fontDefault = panel.querySelector( “[data-bm-font-default]” ); var fontValue = panel.querySelector( “[data-bm-font-value]” ); var lineInput = panel.querySelector( “[data-bm-line-height]” ); var lineValue = panel.querySelector( “[data-bm-line-value]” ); var syllablesButton = panel.querySelector( “[data-bm-syllables]” ); var bionicButton = panel.querySelector( “[data-bm-bionic]” ); var resetButton = panel.querySelector( “[data-bm-reset]” ); var state = loadSettings(); var advancedId = “bm-reader-advanced-” + index; var targets = []; var originalHTML = new Map(); if (advanced) { advanced.id = advancedId; } if ( advancedToggle ) { advancedToggle.setAttribute( “aria-controls”, advancedId ); } panel.setAttribute( “data-bm-js”, “ready” ); /* ================================================== TARGETS ================================================== */ function ensureTargets() { var found = discoverTargets( panel ); found.forEach( function (element) { if ( !originalHTML.has( element ) ) { originalHTML.set( element, element.innerHTML ); element.setAttribute( “data-bm-reading-target”, “” ); } } ); targets = found; panel.setAttribute( “data-bm-target-count”, String( targets.length ) ); return ( targets.length > 0 ); } /* ================================================== REMOVE READING LINE ================================================== */ function removeReadingLine() { targets.forEach( function (element) { element.classList.remove( “bm-reader-line-active” ); } ); } /* ================================================== UPDATE UI ================================================== */ function updateUI() { if ( fontValue ) { fontValue.textContent = state.fontSize + ” px”; } if ( fontMinus ) { fontMinus.disabled = state.fontSize = MAX_FONT_SIZE; } if ( lineInput ) { lineInput.value = String( state.lineHeight ); } if ( lineValue ) { lineValue.textContent = Number( state.lineHeight ) .toFixed(2) .replace( “.”, “,” ); } if ( syllablesButton ) { syllablesButton.setAttribute( “aria-pressed”, state.syllables ? “true” : “false” ); } if ( bionicButton ) { bionicButton.setAttribute( “aria-pressed”, state.bionic ? “true” : “false” ); } panel.querySelectorAll( “[data-bm-theme]” ) .forEach( function (button) { button.classList.toggle( “is-active”, button.getAttribute( “data-bm-theme” ) === state.theme ); } ); panel.querySelectorAll( “[data-bm-width]” ) .forEach( function (button) { button.classList.toggle( “is-active”, button.getAttribute( “data-bm-width” ) === state.width ); } ); panel.querySelectorAll( “[data-bm-align]” ) .forEach( function (button) { button.classList.toggle( “is-active”, button.getAttribute( “data-bm-align” ) === state.align ); } ); panel.querySelectorAll( “[data-bm-tool]” ) .forEach( function (button) { var key = button.getAttribute( “data-bm-tool” ); button.setAttribute( “aria-pressed”, state[key] ? “true” : “false” ); } ); panel.querySelectorAll( “[data-bm-font]” ) .forEach( function (button) { button.classList.toggle( “is-active”, button.getAttribute( “data-bm-font” ) === state.font ); } ); } /* ================================================== RESTORE ORIGINAL TEXT ================================================== */ function restoreOriginalText() { targets.forEach( function (element) { if ( originalHTML.has( element ) ) { element.innerHTML = originalHTML.get( element ); } } ); } /* ================================================== APPLY CONTENT SETTINGS ================================================== */ function applyContentSettings() { if ( !ensureTargets() ) { return; } restoreOriginalText(); var widths = { narrow: “620px”, medium: “760px”, wide: “980px” }; var maxWidth = widths[ state.width ] || widths.medium; var resolvedTheme = state.theme; if ( resolvedTheme === “system” ) { resolvedTheme = window.matchMedia && window.matchMedia( “(prefers-color-scheme: dark)” ) .matches ? “dark” : “light”; } targets.forEach( function (element) { element.style.setProperty( “font-size”, state.fontSize + “px”, “important” ); element.style.setProperty( “line-height”, String( state.lineHeight ), “important” ); element.style.setProperty( “font-family”, getFontFamily( state.font ), “important” ); element.style.setProperty( “text-align”, state.align, “important” ); element.style.setProperty( “max-width”, maxWidth, “important” ); element.style.setProperty( “margin-left”, “auto”, “important” ); element.style.setProperty( “margin-right”, “auto”, “important” ); if ( state.boldText ) { element.style.setProperty( “font-weight”, “650”, “important” ); } else { element.style.removeProperty( “font-weight” ); } if ( state.uppercase ) { element.style.setProperty( “text-transform”, “uppercase”, “important” ); } else { element.style.removeProperty( “text-transform” ); } if ( state.dyslexia ) { element.style.setProperty( “font-family”, ‘”Atkinson Hyperlegible”, Arial, sans-serif’, “important” ); } element.classList.toggle( “bm-reader-line-enabled”, state.readingLine ); element.setAttribute( “data-bm-reader-theme”, resolvedTheme ); if ( resolvedTheme === “dark” ) { element.style.setProperty( “color”, “#f5f7fa”, “important” ); element.style.setProperty( “background-color”, “#17191f”, “important” ); } else if ( resolvedTheme === “warm” ) { element.style.setProperty( “color”, “#2a2118”, “important” ); element.style.setProperty( “background-color”, “#fff8e9”, “important” ); } else if ( resolvedTheme === “gray” ) { element.style.setProperty( “color”, “#1f2328”, “important” ); element.style.setProperty( “background-color”, “#f1f3f5”, “important” ); } else { element.style.removeProperty( “color” ); element.style.removeProperty( “background-color” ); } } ); if ( state.coloredSyllables ) { targets.forEach( applyColoredSyllables ); } else if ( state.syllables ) { targets.forEach( applySyllables ); } if ( state.bionic || state.font === “bionic” ) { targets.forEach( applyBionic ); } } /* ================================================== APPLY SETTINGS ================================================== */ function applySettings() { updateUI(); applyContentSettings(); saveSettings( state ); } /* ================================================== ADVANCED BUTTON ================================================== */ if ( advancedToggle && advanced && advancedLabel ) { advancedToggle.addEventListener( “click”, function () { var expanded = advancedToggle.getAttribute( “aria-expanded” ) === “true”; advancedToggle.setAttribute( “aria-expanded”, expanded ? “false” : “true” ); advanced.hidden = expanded; advancedLabel.textContent = expanded ? “Mai multe opțiuni” : “Mai puține opțiuni”; } ); } /* ================================================== FONT MINUS ================================================== */ if ( fontMinus ) { fontMinus.addEventListener( “click”, function () { state.fontSize = Math.max( MIN_FONT_SIZE, state.fontSize – FONT_STEP ); applySettings(); } ); } /* ================================================== FONT PLUS ================================================== */ if ( fontPlus ) { fontPlus.addEventListener( “click”, function () { state.fontSize = Math.min( MAX_FONT_SIZE, state.fontSize + FONT_STEP ); applySettings(); } ); } /* ================================================== DEFAULT FONT SIZE ================================================== */ if ( fontDefault ) { fontDefault.addEventListener( “click”, function () { state.fontSize = DEFAULTS.fontSize; applySettings(); } ); } /* ================================================== LINE HEIGHT ================================================== */ if ( lineInput ) { lineInput.addEventListener( “input”, function () { state.lineHeight = Number( lineInput.value ); applySettings(); } ); } /* ================================================== SYLLABLES ================================================== */ if ( syllablesButton ) { syllablesButton.addEventListener( “click”, function () { state.syllables = !state.syllables; applySettings(); } ); } /* ================================================== BIONIC ================================================== */ if ( bionicButton ) { bionicButton.addEventListener( “click”, function () { state.bionic = !state.bionic; applySettings(); } ); } /* ================================================== THEMES ================================================== */ panel.querySelectorAll( “[data-bm-theme]” ) .forEach( function (button) { button.addEventListener( “click”, function () { state.theme = button.getAttribute( “data-bm-theme” ); applySettings(); } ); } ); /* ================================================== WIDTH ================================================== */ panel.querySelectorAll( “[data-bm-width]” ) .forEach( function (button) { button.addEventListener( “click”, function () { state.width = button.getAttribute( “data-bm-width” ); applySettings(); } ); } ); /* ================================================== ALIGN ================================================== */ panel.querySelectorAll( “[data-bm-align]” ) .forEach( function (button) { button.addEventListener( “click”, function () { state.align = button.getAttribute( “data-bm-align” ); applySettings(); } ); } ); /* ================================================== TOOLS ================================================== */ panel.querySelectorAll( “[data-bm-tool]” ) .forEach( function (button) { button.addEventListener( “click”, function () { var tool = button.getAttribute( “data-bm-tool” ); if ( typeof state[tool] === “boolean” ) { state[tool] = !state[tool]; if ( tool === “dyslexia” && state.dyslexia ) { state.font = “atkinson”; } applySettings(); } } ); } ); /* ================================================== FONT SELECTOR ================================================== */ panel.querySelectorAll( “[data-bm-font]” ) .forEach( function (button) { button.addEventListener( “click”, function () { state.font = button.getAttribute( “data-bm-font” ); state.dyslexia = state.font === “atkinson”; if ( state.font === “bionic” ) { state.bionic = true; } applySettings(); } ); } ); /* ================================================== RESET ================================================== */ if ( resetButton ) { resetButton.addEventListener( “click”, function () { state = cloneDefaults(); try { localStorage.removeItem( STORAGE_KEY ); } catch (error) {} applySettings(); } ); } /* ================================================== READING LINE ================================================== */ document.addEventListener( “pointermove”, function (event) { if ( !state.readingLine || !targets.length ) { return; } var target = event.target.closest ? event.target.closest( “[data-bm-reading-target]” ) : null; if ( !target || targets.indexOf( target ) === -1 ) { return; } removeReadingLine(); target.classList.add( “bm-reader-line-active” ); } ); document.addEventListener( “pointerleave”, removeReadingLine, true ); /* ================================================== SYSTEM THEME CHANGE ================================================== */ if ( window.matchMedia ) { var media = window.matchMedia( “(prefers-color-scheme: dark)” ); var systemThemeChanged = function () { if ( state.theme === “system” ) { applyContentSettings(); } }; if ( media.addEventListener ) { media.addEventListener( “change”, systemThemeChanged ); } else if ( media.addListener ) { media.addListener( systemThemeChanged ); } } /* ================================================== INITIAL APPLY ================================================== */ applySettings(); /* * Retry pentru page buildere care încarcă textul * puțin mai târziu. */ [ 250, 750, 1500, 3000 ] .forEach( function (delay) { window.setTimeout( function () { if ( !targets.length ) { applyContentSettings(); } }, delay ); } ); } /* ====================================================== START ALL READERS ====================================================== */ function startReaders() { document.querySelectorAll( “[data-bm-reader]” ) .forEach( function ( panel, index ) { if ( panel.getAttribute( “data-bm-initialized” ) === “1” ) { return; } panel.setAttribute( “data-bm-initialized”, “1” ); initReader( panel, index + 1 ); } ); } /* ====================================================== DOM READY ====================================================== */ if ( document.readyState === “loading” ) { document.addEventListener( “DOMContentLoaded”, startReaders, { once: true } ); } else { startReaders(); } })();

Melc, melc,codobelc,

Scoate coarne bourești

Și te du la baltă,

De bea apă caldă;

Și te du la Dunăre,

De bea apa tulbure;

Și te suie pe buștean,

De mănâncă leuștean

Și te suie pe uluci,

De mănâncă mere dulci,

Și te suie pe butoi,

De mănâncă usturoi.