from pathlib import Path
import html, json

THEME=Path('/opt/cosmosluminosity/content/themes/clean')

def esc(s): return html.escape(s, quote=True)
def txt(tag,ru,en,lang,attrs='',cls=''):
    visible=ru if lang=='ru' else en
    c=f' class="{cls}"' if cls else ''
    a=(' '+attrs.strip()) if attrs.strip() else ''
    return f'<{tag}{c}{a} data-ru="{esc(ru)}" data-en="{esc(en)}">{html.escape(visible)}</{tag}>'
def span(ru,en,lang,cls=''):
    return txt('span',ru,en,lang,cls=cls)
def link(ru,en,lang,href,cls=''):
    return txt('a',ru,en,lang,attrs=f'href="{href}"',cls=cls)

def route(lang,ru_path,en_path): return ru_path if lang=='ru' else en_path

def build(lang):
    title_ru='Cosmos Luminosity — продуманный профессиональный переход'
    title_en='Cosmos Luminosity — thoughtful professional transition'
    desc_ru='Целостное сопровождение профессионального перехода для состоявшихся женщин — через мышление, тело, состояние и данные из реальной жизни.'
    desc_en='Whole-person professional transition for accomplished women—guided by mind, body, state and real-world evidence.'
    L=[]
    L.append(f'<div data-title-ru="{esc(title_ru)}" data-title-en="{esc(title_en)}"></div>')
    L.append('<section class="hero" aria-labelledby="hero-title">')
    L.append('<picture><source type="image/avif" srcset="{{asset "images/touchstone-480.avif"}} 480w, {{asset "images/touchstone-640.avif"}} 640w, {{asset "images/touchstone-960.avif"}} 960w, {{asset "images/touchstone-1440.avif"}} 1440w"><source type="image/webp" srcset="{{asset "images/touchstone-480.webp"}} 480w, {{asset "images/touchstone-640.webp"}} 640w, {{asset "images/touchstone-960.webp"}} 960w, {{asset "images/touchstone-1440.webp"}} 1440w"><img class="hero-art" src="{{asset "images/touchstone-2026.jpg"}}" srcset="{{asset "images/touchstone-480.webp"}} 480w, {{asset "images/touchstone-640.webp"}} 640w, {{asset "images/touchstone-960.webp"}} 960w, {{asset "images/touchstone-1440.webp"}} 1440w" sizes="(max-width:650px) 120vw, 54vw" width="1441" height="2560" fetchpriority="high" decoding="async" alt="TOUCHSTONE — artwork by Margarita Rudomanova, 2026"></picture><span class="hero-glitch" aria-hidden="true"></span>')
    L.append('<div class="hero-copy">'+txt('p','Для состоявшихся женщин в профессиональном переходе','For accomplished women in professional transition',lang,cls='eyebrow')+'<h1 id="hero-title">'+span('Тебе не требуется начинать с нуля,','You do not have to start over',lang)+'<br>'+span('чтобы изменить то, как ты работаешь.','to change the way you work.',lang,'accent')+'</h1>'+txt('p','Cosmos Luminosity сопровождает состоявшихся женщин между профессиональной главой, которую они переросли, и следующей, которая ещё не стала ясной. Здесь мышление, тело, состояние, внутреннее знание и реальные обстоятельства складываются в направление, которое можно проверить в жизни.','Cosmos Luminosity guides accomplished women between an outgrown professional chapter and a next one that is not yet clear. Here, mind, body, state, inner knowing and real circumstances become a direction you can test in life.',lang,cls='hero-lead')+'<div class="hero-actions">'+link('Определить, что меняется','Map what needs to change',lang,'#threshold','button primary')+link('Начать с вопроса','Begin with a question',lang,route(lang,'/magic-cloud/','/en/magic-cloud/'),'button')+'</div>'+txt('small','Сохрани то, что по-прежнему ценно. Проверь то, что приходит следующим.','Preserve what still matters. Test what comes next.',lang,cls='hero-note')+'</div></section>')
    nav=[('#threshold','Переход','Transition'),('#doors','Узнавание','Recognition'),('#difference','Подход','Approach'),('#method','Метод','Method'),('#path','Маршрут','Route'),('#creator','Маргарита','Margarita')]
    L.append('<nav class="local-nav" aria-label="On this page"><div class="local-nav-inner">'+''.join(link(r,e,lang,h) for h,r,e in nav)+'</div></nav>')
    L.append('<section class="section threshold" id="threshold" aria-labelledby="threshold-title"><div class="section-inner"><div class="threshold-grid" data-reveal><div>'+txt('p','01 · Профессиональное между','01 · The professional in-between',lang,cls='section-kicker')+'<h2 class="display" id="threshold-title">'+span('Ты не потеряла направление. Ты ','You have not lost direction. You are ',lang)+span('между профессиональными главами.','between professional chapters.',lang,'accent')+'</h2></div>'+txt('p','Прежняя роль может всё ещё приносить статус, доход и признание — и одновременно перестать вмещать тебя. Неопределённость здесь не означает отсутствие направления: разные источники твоей информации ещё складываются в новую последовательность.','Your current role may still bring status, income and recognition—and no longer hold all of you. Uncertainty here is not the absence of direction: different sources of your own information are still becoming a new sequence.',lang,cls='threshold-note')+'</div><div class="both-true" data-reveal>'+txt('p','Я больше не хочу продолжать прежним способом.','I no longer want to continue in the same way.',lang)+txt('i','и','and',lang)+txt('p','Я не хочу совершать безрассудный прыжок.','I do not want to make a reckless leap.',lang)+'</div></div></section>')
    doors=[
    ('Когда успех стал тесным','When success has become too small','Достигнутое всё ещё ценно — и больше не рассказывает всю правду о тебе.','What you built still matters—and no longer tells the whole truth about you.','Карьера, бизнес или экспертная роль по-прежнему работают снаружи, но внутри уже становится слышен другой способ жить и работать.','Your career, business or expert identity still works on the outside, while another way of living and working is becoming audible within.'),
    ('Изменить работу, не обнуляя себя','Change your work without erasing yourself','Профессиональная перемена не отменяет твоё мастерство.','Professional change does not cancel your mastery.','Опыт, связи, репутация, доходный потенциал и созданный образ жизни могут стать материалом следующей главы, а не ценой за неё.','Your experience, relationships, reputation, earning potential and way of life can become material for the next chapter—not the price you pay for it.'),
    ('Когда возможных направлений несколько','When several directions are possible','Выбор следующего эксперимента не закрывает все остальные двери.','Choosing the next experiment does not close every other door.','Можно сохранить полную карту своих интересов и дать одному направлению достаточно внимания, чтобы получить реальные данные.','You can keep the full map of your interests and give one direction enough attention to produce real evidence.'),
    ('Когда советов уже достаточно','When you already have enough advice','Следующий ответ не обязан приходить от нового внешнего авторитета.','The next answer does not have to come from another external authority.','Коучи, системы, символы и практики могут расширять видение. Различение, проверка и окончательный выбор остаются твоими.','Mentors, systems, symbols and practices can widen what you see. Discernment, testing and the final choice remain yours.'),
    ('Внутреннее знание и реальность','Inner knowing and reality','Внутренний сигнал становится полезным, когда его можно различить и проверить.','An inner signal becomes useful when you can discern and test it.','Мышление, тело, состояние и желание не обязаны давать один мгновенный ответ. Их можно услышать по отдельности, соотнести с обстоятельствами и перевести в действие.','Mind, body, state and desire do not have to produce one instant answer. You can hear them separately, relate them to your circumstances and translate them into action.'),
    ('Проверить до большого решения','Test before a major decision','Ясность может появиться после небольшого обратимого шага, а не до него.','Clarity may arrive after a small reversible step—not before it.','Разговор, пилот, пробный проект или новый ритм работы дают данные, на которые можно опереться перед более крупным выбором.','A conversation, pilot, trial project or new work rhythm can create evidence before a larger choice.')]
    d=''.join('<div class="door">'+txt('span',a,b,lang,cls='door-no')+txt('h3',c,d,lang)+txt('p',e,f,lang)+'</div>' for a,b,c,d,e,f in doors)
    L.append('<section class="section doors" id="doors" aria-labelledby="doors-title"><div class="section-inner"><div class="door-head" data-reveal>'+txt('p','02 · Узнаваемые ситуации','02 · Recognizable situations',lang,cls='section-kicker')+'<h2 class="display" id="doors-title">'+span('Один профессиональный переход. ','One professional transition. ',lang)+span('Разные точки входа.','Different ways in.',lang,'accent')+'</h2>'+txt('p','Ты можешь узнать себя в одной ситуации или сразу в нескольких. Во всех них вопрос один: каким образом изменить профессиональную жизнь, не стирая уже созданное?','You may recognize yourself in one situation—or several at once. The question beneath them is the same: how can your professional life change without erasing what you have built?',lang,cls='section-lead')+'</div><div class="door-grid" data-reveal>'+d+'</div></div></section>')
    qs=[('Я действительно переросла эту работу — или просто истощена?','Have I truly outgrown this work—or am I depleted?'),('Что в моей профессиональной главе завершилось, а что стоит сохранить?','What in my professional chapter has ended—and what is worth preserving?'),('Какие продолжения реалистичны с моими ресурсами и обязательствами?','What continuations are realistic with my resources and responsibilities?'),('Каким образом проверить новое направление до необратимого решения?','How can I test a new direction before making an irreversible decision?'),('Какой следующий шаг даст мне данные, а не только ещё больше мыслей?','What next step will give me evidence—not only more thoughts?')]
    q=''.join(f'<div class="question"><span>{i:02}</span>'+txt('p',r,e,lang)+'</div>' for i,(r,e) in enumerate(qs,1))
    L.append('<section class="section questions" aria-labelledby="questions-title"><div class="section-inner">'+txt('p','Вопросы продуманного перехода','Questions of a thoughtful transition',lang,cls='section-kicker')+'<h2 class="display" id="questions-title">'+span('Что ты, возможно, ','What you may be ',lang)+span('пытаешься различить сейчас.','trying to discern now.',lang,'accent')+'</h2><div class="question-list" data-reveal>'+q+'</div></div></section>')
    items=[('Сохранить ценное','Preserve what matters','Опыт и созданная тобой жизнь становятся опорой перехода, а не тем, от чего требуется отказаться.','Your experience and the life you built become support for the transition—not something you are asked to abandon.'),('Различить сигналы','Discern the signals','Разум, тело, состояние, желание, страх и привычка получают отдельный голос — без автоматического подчинения одному из них.','Mind, body, state, desire, fear and habit each get a voice—without automatically obeying any one of them.'),('Соотнести с реальностью','Relate it to reality','Внутреннее знание встречается с деньгами, временем, обязательствами, отношениями и реальными возможностями.','Inner knowing meets money, time, responsibilities, relationships and real opportunities.'),('Проверить обратимым шагом','Test with a reversible step','Небольшой эксперимент создаёт обратную связь до того, как ты примешь более крупное решение. Ты остаёшься выбирающей.','A small experiment creates feedback before you make a larger decision. You remain the one who chooses.')]
    ni=''.join('<div class="not-item">'+txt('small',a,b,lang)+txt('p',c,d,lang)+'</div>' for a,b,c,d in items)
    L.append('<section class="section difference" id="difference" aria-labelledby="difference-title"><div class="section-inner"><div class="difference-grid"><div class="difference-copy" data-reveal>'+txt('p','03 · Подход Cosmos Luminosity','03 · The Cosmos Luminosity approach',lang,cls='section-kicker')+'<h2 class="display" id="difference-title">'+span('Не готовый ответ. ','Not a ready-made answer. ',lang)+span('Твоя собственная карта перехода.','Your own transition map.',lang,'accent')+'</h2>'+txt('p','Ты уже целостна и несёшь ресурсы, желание, выбор, мастерство и несколько видов интеллекта. Cosmos Luminosity помогает услышать разные источники собственной информации, различить их, соотнести с реальностью и проверить следующий шаг, сохраняя своё авторство.','You are already whole. You carry resources, desire, choice, mastery and more than one kind of intelligence. Cosmos Luminosity helps you hear different sources of your own information, discern them, relate them to reality and test a next step while keeping your authorship.',lang,cls='section-lead')+'</div><div class="not-list" data-reveal>'+ni+'</div></div>'+txt('p','Не начинать с нуля. Сохранить важное, различить своё и проверить то, что приходит следующим.','Do not start from zero. Preserve what matters, discern what is yours and test what comes next.',lang,cls='manifesto')+'</div></section>')
    steps=[('Услышать','Listen','Что завершилось? Что хочется сохранить? Что становится живым?','What has ended? What do you want to preserve? What is becoming alive?'),('Различить','Discern','Что сообщает разум, тело и состояние? Где желание, страх, привычка или чужое ожидание?','What are mind, body and state communicating? What is desire, fear, habit or someone else’s expectation?'),('Проверить','Test','Какое реалистичное направление можно проверить небольшим обратимым действием?','What credible direction can be tested through a small reversible action?'),('Пересмотреть данные','Review the evidence','Что показал эксперимент — и какой выбор теперь опирается не только на предположение?','What did the experiment reveal—and which choice now rests on more than assumption?')]
    st=''.join(f'<div class="step"><i>{i}</i><div>'+txt('b',a,b,lang)+txt('span',c,d,lang)+'</div></div>' for i,(a,b,c,d) in enumerate(steps,1))
    L.append('<section class="section method" id="method" aria-labelledby="method-title"><div class="section-inner method-grid"><div data-reveal>'+txt('p','04 · От сигнала к свидетельству','04 · From signal to evidence',lang,cls='section-kicker')+'<h2 class="display" id="method-title">'+span('Ясность становится ','Clarity becomes ',lang)+span('проверяемой.','testable.',lang,'accent')+'</h2><div class="method-steps">'+st+'</div></div><div class="method-card" data-reveal>'+txt('p','«Какой следующий шаг даст мне достаточно реальных данных для следующего выбора?»','“What next step will give me enough real-world evidence for the choice after that?”',lang)+txt('small','Вопрос продуманного перехода','A thoughtful-transition question',lang)+'</div></div></section>')
    cards=[('Необязательный символический слой','Optional symbolic layer','Magic Cloud','Magic Cloud','Принеси один вопрос и получи символическую перспективу. Это не предсказание и не решение, а дополнительный материал для собственного различения.','Bring one question and receive a symbolic perspective. It is not a prediction or decision, but optional material for your own discernment.','Начать с вопроса →','Begin with a question →',route(lang,'/magic-cloud/','/en/magic-cloud/'),''),('Основной самостоятельный маршрут','Core self-guided route','Gateway: Between Identities','Gateway: Between Identities','Конечный маршрут от сигнала к личной карте перехода, реалистичным направлениям и одному следующему шагу, который можно проверить в жизни.','A finite route from signal to a personal transition map, credible directions and one next step you can test in life.','Пройти маршрут →','Enter the route →',route(lang,'/gateways/','/en/gateways/'),' current'),('Продолжение и интеграция','Continuation & integration','LumoSide','LumoSide','Пространство после основного маршрута: вещание Маргариты, сезонные практики и возвращение к следующему выбору без индивидуальных разборов.','An ongoing space after the core route: Margarita’s transmissions, seasonal practices and return to the next choice—without individual readings.','Открыть LumoSide →','Enter LumoSide →',route(lang,'/lumoside/','/en/lumoside/'),'')]
    pc=''.join(f'<article class="path-card{x}">'+txt('span',a,b,lang,cls='path-no')+txt('h3',c,d,lang)+txt('p',e,f,lang)+link(g,h,lang,u)+'</article>' for a,b,c,d,e,f,g,h,u,x in cards)
    L.append('<section class="section path" id="path" aria-labelledby="path-title"><div class="section-inner">'+txt('p','05 · Маршрут Cosmos Luminosity','05 · The Cosmos Luminosity route',lang,cls='section-kicker')+'<h2 class="display" id="path-title">'+span('Войди через тот этап, ','Enter at the stage ',lang)+span('который соответствует твоему переходу сейчас.','that matches your transition now.',lang,'accent')+'</h2>'+txt('p','Каждый формат имеет отдельную задачу: символическая перспектива, основной маршрут перехода или последующая интеграция. До LumoSide весь путь проходит самостоятельно.','Each format has a distinct role: symbolic perspective, the core transition route or ongoing integration. Everything before LumoSide is self-guided.',lang,cls='section-lead')+'<div class="path-grid" data-reveal>'+pc+'</div></div></section>')
    L.append('<section class="section creator" id="creator" aria-labelledby="creator-title"><div class="section-inner creator-grid"><figure class="art-frame" data-reveal><picture><source type="image/avif" srcset="{{asset "images/cosmic-tree-640.avif"}} 640w, {{asset "images/cosmic-tree-1280.avif"}} 1280w"><source type="image/webp" srcset="{{asset "images/cosmic-tree-640.webp"}} 640w, {{asset "images/cosmic-tree-1280.webp"}} 1280w"><img src="{{asset "images/cosmic-tree.jpg"}}" width="1280" height="1195" loading="lazy" decoding="async" alt="Cosmic Tree — artwork by Margarita Rudomanova"></picture>'+txt('figcaption','Spazio Dimensioni · авторское искусство','Spazio Dimensioni · original art',lang,cls='art-caption')+'</figure><div class="creator-copy" data-reveal>'+txt('p','06 · Создательница','06 · Creator',lang,cls='section-kicker')+'<h2 class="display" id="creator-title">'+span('Маргарита','Margarita',lang)+'<br>'+span('Рудоманова','Rudomanova',lang,'accent')+'</h2>'+txt('p','Я создала Cosmos Luminosity не для того, чтобы говорить женщине, какой профессиональный путь выбрать, а чтобы она могла услышать собственные источники информации, различить их и проверить следующий шаг, сохраняя своё авторство.','I created Cosmos Luminosity not to tell a woman which professional path to choose, but so she can hear her own sources of information, discern them and test a next step while keeping her authorship.',lang,cls='lead')+txt('p','В моей работе встречаются мышление, тело, состояние, внутреннее знание, практическая реальность и — когда это полезно — символический слой. Ни один источник не получает абсолютной власти. Они становятся навигацией, а выбор остаётся у тебя.','My work brings together mind, body, state, inner knowing, practical reality and—when useful—a symbolic layer. No single source receives absolute authority. Together they become navigation, while the choice remains yours.',lang,cls='body')+link('Узнать подход','Explore the approach',lang,'#difference','button')+'</div></div></section>')
    L.append('<section class="section entry" id="entry" aria-labelledby="entry-title"><div class="section-inner" data-reveal>'+txt('p','07 · The Thoughtful Transition','07 · The Thoughtful Transition',lang,cls='section-kicker')+'<h2 class="display" id="entry-title">'+span('Сохраняй контакт с тем, ','Stay close to what ',lang)+span('что показывают внутренние сигналы и реальная жизнь.','your inner signals and real life reveal.',lang,'accent')+'</h2>'+txt('p','Письма для состоявшихся женщин о продуманном профессиональном переходе: что завершилось, что сохранить, каким данным доверять и каким образом проверять следующую главу в реальной жизни.','Letters for accomplished women navigating thoughtful professional transition: what has ended, what to preserve, which signals to trust and how to test a next chapter in real life.',lang,cls='entry-copy')+txt('p','Обычно 1–2 содержательных письма в месяц. Без ежедневного шума и готовых ответов за тебя.','Usually 1–2 considered letters each month. No daily noise and no ready-made answers for you.',lang,cls='entry-frequency')+'<form class="newsletter-form" data-newsletter-form novalidate><label class="newsletter-honeypot" aria-hidden="true">Website<input type="text" name="website" tabindex="-1" autocomplete="off"></label>'+txt('label','Твой email','Your email',lang,attrs='for="newsletter-email"',cls='newsletter-label')+'<div class="newsletter-row"><input class="newsletter-email" id="newsletter-email" name="email" type="email" inputmode="email" autocomplete="email" required maxlength="254" placeholder="name@example.com" aria-describedby="newsletter-consent newsletter-status">'+txt('button','Получать письма','Receive the letters',lang,attrs='type="submit"',cls='newsletter-submit')+'</div><p class="newsletter-status" id="newsletter-status" role="status" aria-live="polite"></p>'+txt('small','Отправляя форму, ты соглашаешься с политикой конфиденциальности.','By submitting, you agree to the privacy policy.',lang,attrs='id="newsletter-consent"',cls='newsletter-consent')+'</form></div></section>')
    schema={"@context":"https://schema.org","@type":"WebSite","name":"Cosmos Luminosity","url":"https://www.cosmosluminosity.com/" if lang=='ru' else "https://www.cosmosluminosity.com/en/","description":desc_ru if lang=='ru' else desc_en,"inLanguage":lang,"creator":{"@type":"Person","name":"Margarita Rudomanova"}}
    L.append('<script type="application/ld+json">'+json.dumps(schema,ensure_ascii=False,separators=(',',':'))+'</script>')
    return title_ru,title_en,desc_ru,desc_en,'\n'.join(L)

for lang,name,layout in [('ru','index.hbs','default'),('en','index-en.hbs','default-en')]:
    p=THEME/name
    old=p.read_text()
    css_end=old.index('</style>')+8
    script_start=old.index('<script>\n',css_end)
    tr,te,dr,de,body=build(lang)
    header=f'{{{{!< {layout}}}}}\n{{{{#contentFor "page_title"}}}}{tr if lang=="ru" else te}{{{{/contentFor}}}}\n{{{{#contentFor "page_description"}}}}{dr if lang=="ru" else de}{{{{/contentFor}}}}\n{{{{#contentFor "canonical_url"}}}}https://www.cosmosluminosity.com/{"en/" if lang=="en" else ""}{{{{/contentFor}}}}\n{{{{#contentFor "ru_url"}}}}https://www.cosmosluminosity.com/{{{{/contentFor}}}}\n{{{{#contentFor "en_url"}}}}https://www.cosmosluminosity.com/en/{{{{/contentFor}}}}\n'
    css=old[old.index('<style>'):css_end]
    p.write_text(header+css+'\n'+body+'\n'+old[script_start:])

# Global metadata, navigation anchors and footer description.
for name in ['default.hbs','default-en.hbs']:
    p=THEME/name
    s=p.read_text()
    repl={
    'Cosmos Luminosity — практики мышления, состояния и тела для живого выбора.':'Cosmos Luminosity — целостное сопровождение профессионального перехода для состоявшихся женщин.',
    'Cosmos Luminosity — practices for thinking, state, body and meaning that support living choice.':'Cosmos Luminosity — whole-person professional transition for accomplished women.',
    'Cosmos Luminosity — живой выбор':'Cosmos Luminosity — продуманный профессиональный переход',
    'Cosmos Luminosity — living choice':'Cosmos Luminosity — thoughtful professional transition',
    '/#metasystem':'/#difference','/en/#metasystem':'/en/#difference','/#gateways':'/#path','/en/#gateways':'/en/#path',
    'Практики мышления, состояния, тела и смысла.':'Профессиональный переход через мышление, тело, состояние и данные из реальной жизни.',
    'Practices for thinking, state, body and meaning.':'Professional transition through mind, body, state and real-world evidence.',
    'data-ru="Форматы" data-en="Formats">Форматы':'data-ru="Маршрут" data-en="Route">Маршрут',
    'data-ru="Форматы" data-en="Formats">Formats':'data-ru="Маршрут" data-en="Route">Route',
    'data-ru="Как это работает" data-en="How it works">Как это работает':'data-ru="Метод" data-en="Method">Метод',
    'data-ru="Как это работает" data-en="How it works">How it works':'data-ru="Метод" data-en="Method">Method'}
    for a,b in repl.items(): s=s.replace(a,b)
    p.write_text(s)
print('updated', *(str(THEME/x) for x in ['index.hbs','index-en.hbs','default.hbs','default-en.hbs']))
