{"id":5391,"date":"2026-09-25T13:04:40","date_gmt":"2026-09-25T13:04:40","guid":{"rendered":"https:\/\/kblack.vn\/?page_id=5391"},"modified":"2026-10-30T11:23:38","modified_gmt":"2026-10-30T04:23:38","slug":"photo-lab","status":"publish","type":"page","link":"https:\/\/kblack.vn\/en\/photo-lab\/","title":{"rendered":"PHOTO LAB"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"5391\" class=\"elementor elementor-5391\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-20459b6 elementor-section-full_width elementor-section-height-default elementor-section-height-default\" data-id=\"20459b6\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-52313ad\" data-id=\"52313ad\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-98134a4 elementor-widget elementor-widget-html\" data-id=\"98134a4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"kb-sr\" style=\"position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0\">Photo Lab \u2013 H\u1ecdc nhi\u1ebfp \u1ea3nh mi\u1ec5n ph\u00ed online &amp; m\u00f4 ph\u1ecfng \u00e1nh s\u00e1ng studio 3D<\/h1><!DOCTYPE html>\n<html lang=\"vi\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>K-BLACK Photo Lab<\/title>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/three@0.128.0\/build\/three.min.js\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/three@0.128.0\/examples\/js\/controls\/OrbitControls.js\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/three@0.128.0\/examples\/js\/lights\/RectAreaLightUniformsLib.js\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/three@0.128.0\/examples\/js\/loaders\/GLTFLoader.js\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/three@0.128.0\/examples\/js\/loaders\/DRACOLoader.js\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/three@0.128.0\/examples\/js\/utils\/SkeletonUtils.js\"><\/script>\n<style>@media(max-width:430px){html body .top .brand>span{display:none!important}}\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Barlow+Condensed:wght@500;600;700&family=Be+Vietnam+Pro:wght@400;500;600;700;800&display=swap');\n:root{--bg:#0a0f1c;--panel:#121a2c;--panel2:#18223a;--line:#243150;--navy:#0c1a36;--blue:#2f6bff;--blue-l:#7aa2ff;--warm:#ffb259;--ink:#e9eef7;--mut:#8e9ab3;--mut2:#5d6985;--ok:#4fd18b;--bad:#ff6b6b}\n*{box-sizing:border-box;margin:0;padding:0}\nhtml,body{height:100%}\nbody{font-family:'Be Vietnam Pro',system-ui,sans-serif;background:var(--bg);color:var(--ink);overflow:hidden;font-size:14px;line-height:1.5}\nbutton{font-family:inherit;cursor:pointer;color:inherit}input,select{font-family:inherit}\nbutton:focus-visible,input:focus-visible,select:focus-visible{outline:2px solid var(--blue-l);outline-offset:2px}\n::-webkit-scrollbar{width:9px;height:9px}::-webkit-scrollbar-thumb{background:#26324f;border-radius:6px}\n.top{height:54px;display:flex;align-items:center;gap:14px;padding:0 16px;border-bottom:1px solid var(--line);background:linear-gradient(180deg,#101830,#0a0f1c)}\n.brand{display:flex;align-items:center;gap:10px;min-width:0}.brand img{height:20px}.brand span{color:var(--mut);font-size:12.5px;border-left:1px solid var(--line);padding-left:10px;white-space:nowrap}\n.tabs{display:flex;gap:4px;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:4px;margin-left:auto}\n.tab{border:none;background:none;padding:7px 16px;border-radius:9px;font-weight:700;font-size:13px;color:var(--mut)}\n.tab.on{background:var(--blue);color:#fff}\n.tacts{display:flex;gap:6px;margin-left:10px}\n.tbtn{background:var(--panel2);border:1px solid var(--line);padding:7px 11px;border-radius:9px;font-size:12px;font-weight:600}\n.tbtn:hover{border-color:var(--blue)}\n.pane{display:none;height:calc(100vh - 54px)}.pane.on{display:flex}\n\/* ===== LEARN ===== *\/\n.rail{width:270px;min-width:240px;border-right:1px solid var(--line);background:var(--panel);overflow-y:auto;padding:16px 12px}\n.prog{margin:0 4px 14px}.prog .bar{height:6px;background:var(--panel2);border-radius:4px;overflow:hidden;margin-top:6px}.prog .bar i{display:block;height:100%;background:var(--blue);width:0;transition:width .3s}\n.prog small{color:var(--mut);font-size:12px}\n.les{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:none;border:1px solid transparent;border-radius:10px;padding:9px 10px;margin-bottom:3px;font-size:13.5px;color:var(--ink)}\n.les:hover{background:var(--panel2)}.les.on{background:#16244a;border-color:#2c4a8f}\n.les .ic{width:26px;height:26px;border-radius:8px;background:var(--panel2);display:flex;align-items:center;justify-content:center;font-size:14px;flex:0 0 auto}\n.les .dn{margin-left:auto;color:var(--ok);font-size:13px}\n.lbody{flex:1;overflow-y:auto;padding:34px 40px 80px}\n.lwrap{max-width:1480px;margin:0 auto}\n.lwrap h1{font-size:34px;line-height:1.15;font-weight:800;letter-spacing:-.5px;margin-bottom:10px}\n.lwrap h2{font-size:19px;font-weight:700;margin:28px 0 10px}\n.lwrap p{color:#c9d2e3;margin-bottom:12px;max-width:80ch}\n.lwrap .lead{font-size:16.5px;color:#dbe3f2}\n.lwrap ul{margin:0 0 14px 20px;color:#c9d2e3}.lwrap li{margin-bottom:6px}\n.lwrap b{color:#fff}\n.tip{border-left:3px solid var(--warm);background:#1c1a17;padding:12px 16px;border-radius:0 10px 10px 0;margin:16px 0;color:#f1dcc0;font-size:13.5px}\n.tbl{width:100%;border-collapse:collapse;margin:8px 0 16px;font-size:13.5px}\n.tbl th{text-align:left;color:var(--mut);font-weight:600;padding:8px 10px;border-bottom:1px solid var(--line)}\n.tbl td{padding:9px 10px;border-bottom:1px solid #1b2540;color:#d6deed;vertical-align:top}\n.sim{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px;margin:18px 0}\n.sim canvas{width:100%;display:block;border-radius:10px;background:#000}\n.simrow{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:14px}\n.simrow.two{grid-template-columns:1fr 1fr}\n.read{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:12px;font-size:13px;color:var(--mut)}\n.read b{font-family:'Barlow Condensed';font-size:20px;color:#fff;font-weight:600;margin-left:4px}\n.verdict{margin-top:10px;padding:10px 14px;border-radius:10px;font-weight:600;font-size:13.5px}\n.verdict.ok{background:#12301f;color:#8ff0b8}.verdict.over{background:#3a2412;color:#ffc98f}.verdict.under{background:#141d3a;color:#9fb8ff}\n.lnav{display:flex;justify-content:space-between;align-items:center;margin-top:34px;padding-top:18px;border-top:1px solid var(--line)}\n.pbtn{background:var(--blue);border:none;color:#fff;padding:10px 18px;border-radius:10px;font-weight:700;font-size:13.5px}\n.gbtn{background:var(--panel2);border:1px solid var(--line);padding:10px 16px;border-radius:10px;font-weight:600;font-size:13px}\n.cards{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin:10px 0 16px}\n.card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px}\n.card h3{font-size:16px;margin-bottom:6px}.card p{font-size:13px;margin-bottom:10px}\n.swrow{display:flex;gap:12px;margin-top:12px}\n.sw{flex:1;border-radius:10px;height:90px;display:flex;align-items:flex-end;padding:8px 10px;font-size:12px;font-weight:600;color:#222}\n.qz{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px;margin-bottom:12px}\n.qz h3{font-size:15px;margin-bottom:10px}\n.qz button.opt{display:block;width:100%;text-align:left;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:9px 12px;margin-bottom:6px;font-size:13.5px}\n.qz button.opt.right{border-color:var(--ok);background:#12301f}.qz button.opt.wrong{border-color:var(--bad);background:#361818}\n.qz .ex{font-size:13px;color:var(--mut);margin-top:6px;display:none}\nlabel.ctl{display:block}\n.ctl{margin-bottom:10px}\n.ctlh{display:flex;justify-content:space-between;font-size:12px;color:var(--mut);margin-bottom:4px}\n.ctlh b{font-family:'Barlow Condensed';font-size:16px;color:#fff;font-weight:600}\ninput[type=range]{width:100%;accent-color:var(--blue)}\nselect,input[type=text],input[type=color]{width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:7px 9px;color:var(--ink);font-size:12.5px}\ninput[type=color]{height:34px;padding:3px}\n.seg{display:flex;gap:4px;flex-wrap:wrap}\n.seg button{background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:6px 10px;font-size:12px;font-weight:600;color:var(--mut)}\n.seg button.on{background:var(--blue);border-color:var(--blue);color:#fff}\n\/* ===== STUDIO ===== *\/\n.sp{width:292px;min-width:270px;background:var(--panel);border-right:1px solid var(--line);overflow-y:auto;padding:14px 13px 60px}\n.sp.r{border-right:none;border-left:1px solid var(--line);width:318px}\n.grp{margin-bottom:18px}\n.grp>h4{font-size:13px;font-weight:700;margin-bottom:10px;color:#fff;display:flex;justify-content:space-between;align-items:center}\n.grp>h4 small{color:var(--mut);font-weight:500;font-size:11.5px}\n.presets{display:grid;grid-template-columns:1fr 1fr;gap:6px}\n.presets button{background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:8px;font-size:12px;font-weight:600;text-align:left}\n.presets button:hover{border-color:var(--warm)}\n.note{font-size:11.5px;color:var(--mut);line-height:1.5;margin-top:4px}\n.warn{font-size:12px;color:#ffc98f;background:#2d1f10;border-radius:8px;padding:7px 10px;margin-top:6px}\n.view{flex:1;position:relative;min-width:0;background:#05070d}\n#view3d{position:absolute;inset:0}\n#view3d canvas{display:block;width:100%;height:100%}\n.vbar{position:absolute;top:12px;left:262px;right:12px;display:flex;gap:6px;justify-content:flex-end;flex-wrap:wrap;z-index:6;pointer-events:none}\n.vgrp{display:flex;gap:2px;background:rgba(12,18,32,.9);border:1px solid var(--line);border-radius:11px;padding:3px;pointer-events:auto;backdrop-filter:blur(6px)}\n.vgrp button{background:none;border:none;padding:6px 10px;border-radius:8px;font-size:12px;font-weight:600;color:var(--mut)}\n.vgrp button:hover{color:#fff}\n.vgrp button.on{background:var(--panel2);color:#fff}\n.vgrp button[data-v].on{color:var(--warm)}\n.labels{position:absolute;inset:0;pointer-events:none;z-index:3;overflow:hidden}\n.lb{position:absolute;left:0;top:0;white-space:nowrap;font-size:11.5px;font-weight:600;will-change:transform}\n.lb.tag{background:rgba(10,15,28,.86);border:1px solid #2c3a5c;border-radius:20px;padding:3px 9px 3px 7px;color:#e9eef7;display:flex;align-items:center;gap:6px}\n.lb.tag i{width:8px;height:8px;border-radius:50%;display:inline-block}\n.lb.tag.sel{border-color:var(--warm);box-shadow:0 0 0 1px var(--warm)}\n.lb.tag.off{opacity:.45}\n.lb.dim{font-family:'Barlow Condensed';font-size:15px;font-weight:600;color:#fff;background:rgba(47,107,255,.88);border-radius:6px;padding:0 6px}\n.lb.dim.h{background:rgba(52,62,88,.9)}\n.hud{position:absolute;left:12px;bottom:12px;right:276px;z-index:5;background:rgba(10,15,28,.92);border:1px solid var(--line);border-radius:12px;padding:9px 13px;font-size:12.5px;color:#cfd8ea;pointer-events:none}\n.hud b{color:#fff}.hud .n{font-family:'Barlow Condensed';font-size:16px;color:#fff;font-weight:600}\n.hud .sep{display:inline-block;width:1px;height:11px;background:#33415f;margin:0 9px;vertical-align:middle}\n.hud .hint{color:var(--mut);font-size:11.5px;margin-top:3px}\n.dragtip{position:fixed;z-index:60;pointer-events:none;background:#0d1322;border:1px solid var(--warm);border-radius:10px;padding:8px 11px;font-size:12px;display:none;box-shadow:0 10px 24px -10px #000;color:#cfd8ea;max-width:250px}\n.dragtip b{color:#fff}.dragtip .n{font-family:'Barlow Condensed';font-size:17px;font-weight:600;color:#fff}.dragtip .mut{color:var(--mut);margin-top:3px}\n.meter .mt{cursor:pointer}.meter.mini .rows,.meter.mini .warn,.meter.mini button{display:none}\n.addrow{display:flex;gap:6px;margin-top:4px}.addrow select{flex:1}\n.pbtn2{background:var(--blue);border:none;color:#fff;border-radius:8px;padding:7px 12px;font-weight:700;font-size:12px;white-space:nowrap}\n.nudge{display:flex;gap:4px;margin:-4px 0 10px}.nudge button{flex:1;background:var(--panel2);border:1px solid var(--line);border-radius:7px;padding:5px 0;font-family:'Barlow Condensed';font-size:14px;font-weight:600}\n.nudge button:hover{border-color:var(--warm)}\n.sect{font-size:11.5px;color:var(--mut);font-weight:600;margin:10px 0 8px;padding-top:10px;border-top:1px solid var(--line)}\n.ctlh b.typ{cursor:pointer;border-bottom:1px dashed #3a4a70}\n.tbtn.ic{min-width:32px;padding:7px 9px}.tbtn[disabled]{opacity:.35;pointer-events:none}\n.meter{position:absolute;top:12px;left:12px;width:236px;background:linear-gradient(180deg,#141c2e,#0d1322);border:1px solid #2a3858;border-radius:14px;padding:12px 14px;z-index:5;box-shadow:0 12px 30px -12px #000}\n.meter .mt{display:flex;justify-content:space-between;color:var(--mut);font-size:11.5px}\n.meter .big{font-family:'Barlow Condensed';font-size:52px;line-height:1;font-weight:700;color:#fff;margin:4px 0 2px;letter-spacing:.5px}\n.meter .sub{font-size:12px;color:var(--mut)}\n.meter .ev{margin-top:8px;padding:6px 9px;border-radius:8px;font-size:12px;font-weight:600}\n.meter .rows{margin-top:8px;border-top:1px solid #243150;padding-top:7px;font-size:12px}\n.meter .rows div{display:flex;justify-content:space-between;padding:2px 0;color:#cfd8ea}\n.meter .rows span.d{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px}\n.meter button{margin-top:8px;width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:6px;font-size:12px;font-weight:600}\n.planbox{position:absolute;right:12px;bottom:12px;width:250px;height:250px;background:rgba(10,15,28,.92);border:1px solid var(--line);border-radius:14px;z-index:5;overflow:hidden}\n.planbox canvas{width:100%;height:100%;display:block;cursor:grab}\n.planbox .pt{position:absolute;left:10px;top:7px;font-size:11px;color:var(--mut);pointer-events:none}\n.povframe{position:absolute;display:none;z-index:4;pointer-events:none;box-shadow:0 0 0 9999px rgba(0,0,0,.55);border:1px solid rgba(255,255,255,.5)}\n.povframe .g{position:absolute;background:rgba(255,255,255,.28)}\n.nogl{position:absolute;inset:0;display:none;align-items:center;justify-content:center;text-align:center;padding:40px;color:var(--mut)}\n.lrow{display:flex;align-items:center;gap:8px;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:8px 10px;margin-bottom:6px;cursor:pointer}\n.lrow.on{border-color:var(--warm)}\n.lrow .d{width:12px;height:12px;border-radius:50%;flex:0 0 auto}\n.lrow .n{flex:1;font-size:13px;font-weight:600;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.lrow .n small{display:block;color:var(--mut);font-weight:500;font-size:11px}\n.lrow .tg{width:34px;height:20px;border-radius:10px;background:#2a3450;position:relative;border:none;flex:0 0 auto}\n.lrow .tg::after{content:\"\";position:absolute;top:3px;left:3px;width:14px;height:14px;border-radius:50%;background:#8e9ab3;transition:left .15s}\n.lrow .tg.on{background:var(--warm)}.lrow .tg.on::after{left:17px;background:#fff}\n.addl{width:100%;background:none;border:1.5px dashed var(--line);border-radius:10px;padding:9px;font-weight:600;font-size:12.5px;color:var(--blue-l)}\n.edit{margin-top:12px;background:#0e1526;border:1px solid var(--line);border-radius:12px;padding:12px}\n.row2{display:grid;grid-template-columns:1fr 1fr;gap:8px}\n.minib{display:flex;gap:6px;margin-top:8px}.minib button{flex:1;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:7px;font-size:12px;font-weight:600}\n.minib button.dg{color:var(--bad)}\n.msg{position:fixed;bottom:16px;left:50%;transform:translateX(-50%);background:var(--panel2);border:1px solid var(--line);border-left:3px solid var(--blue);border-radius:10px;padding:10px 16px;font-size:13px;display:none;z-index:100;box-shadow:0 14px 30px -12px #000}\n.msg.show{display:block}\n.modal{position:fixed;inset:0;background:#04060bcc;z-index:90;display:none;align-items:flex-start;justify-content:center;padding:60px 16px}\n.modal.show{display:flex}\n.mbox{width:100%;max-width:440px;background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px}\n.mbox .srow{display:flex;gap:8px;align-items:center;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:8px 10px;margin-top:6px;font-size:13px}\n.mbox .srow span{flex:1}\n.chh{font-size:11.5px;color:var(--mut2);font-weight:700;margin:16px 8px 6px}\n.crumb{font-size:12.5px;color:var(--mut);margin-bottom:8px}\n.exbox{border:1px solid #2c4a8f;background:#101a33;border-radius:12px;padding:14px 16px;margin-top:26px}\n.exbox h3{font-size:14px;margin-bottom:6px;color:var(--blue-l)}.exbox p{margin:0;color:#d6deed}\n.lnl{display:flex;gap:8px;flex-wrap:wrap}\n.histc{margin-top:10px;background:#0b0f1a;height:auto}\n.ol{margin:0 0 14px 20px;color:#c9d2e3}.ol li{margin-bottom:6px}\n.chkp{margin-bottom:10px}.chkp h2 small{color:var(--mut);font-weight:500;font-size:13px;margin-left:6px}\n.chki{display:flex;gap:10px;align-items:flex-start;background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:10px 12px;margin-bottom:6px;cursor:pointer;color:#d6deed;font-size:14px}\n.chki input{width:17px;height:17px;margin-top:2px;accent-color:var(--ok);flex:0 0 auto}\n.chki.on{border-color:#2e6b4a;background:#10231a;color:#a9e8c4}\n.gl{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:12px}\n.gi{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:10px 12px}.gi b{display:block;color:#fff;font-size:13.5px;margin-bottom:3px}.gi span{color:#b9c3d8;font-size:13px}\n.lwrap>input[type=text]{font-size:14px;padding:10px 12px}\n@media(max-width:760px){.gl{grid-template-columns:1fr}}\n.fig{margin:14px 0}.fig img{width:100%;display:block;border-radius:12px;background:#0b0f1a;aspect-ratio:auto}.fig figcaption{font-size:12.5px;color:var(--mut);margin-top:6px;line-height:1.5}\n.figrow{display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:start}.figrow.three{grid-template-columns:1fr 1fr 1fr}.figrow .fig{margin:0}\n.sqc{max-width:540px;margin:0 auto}\n.card.hasimg img{width:100%;height:170px;object-fit:cover;border-radius:9px;margin-bottom:6px;display:block}.card .cap{font-size:11.5px;color:var(--mut);margin-bottom:8px}\n@media(max-width:760px){.figrow,.figrow.three{grid-template-columns:1fr}}\n\/* ===== game layer ===== *\/\n.player{display:flex;align-items:center;gap:9px;background:linear-gradient(135deg,#17213a,#101628);border:1px solid #2c3a5c;border-radius:12px;padding:4px 12px 4px 4px;margin-left:10px;text-align:left}\n.player:hover{border-color:var(--warm)}\n.player .lv{width:32px;height:32px;border-radius:9px;background:linear-gradient(135deg,#ffb259,#ff7a3d);color:#1a1006;font-family:'Barlow Condensed';font-size:20px;font-weight:700;display:flex;align-items:center;justify-content:center;box-shadow:0 0 14px -2px rgba(255,178,89,.6)}\n.player .pinfo{display:flex;flex-direction:column;gap:2px;min-width:120px}.player .pinfo b{font-size:12px}.player .pinfo small{font-size:10.5px;color:var(--mut);font-family:'Barlow Condensed';letter-spacing:.3px}\n.xpbar{height:5px;background:#26314d;border-radius:3px;overflow:hidden}.xpbar i{display:block;height:100%;width:0;background:linear-gradient(90deg,#ffb259,#ffd699);transition:width .6s cubic-bezier(.2,.8,.2,1)}\n.xpfly{position:fixed;left:50%;top:84px;transform:translateX(-50%);z-index:200;background:#1c1406;border:1px solid var(--warm);color:#ffd699;border-radius:12px;padding:8px 16px;font-family:'Barlow Condensed';font-size:24px;font-weight:700;text-align:center;animation:xpf 2.2s ease forwards;pointer-events:none}\n.xpfly small{display:block;font-family:'Be Vietnam Pro';font-size:11.5px;font-weight:500;color:#e8c89a}\n@keyframes xpf{0%{opacity:0;transform:translate(-50%,10px) scale(.9)}12%{opacity:1;transform:translate(-50%,0) scale(1.05)}20%{transform:translate(-50%,0) scale(1)}80%{opacity:1}100%{opacity:0;transform:translate(-50%,-24px)}}\n.lvup{position:fixed;inset:0;z-index:210;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;background:radial-gradient(circle at center,rgba(255,178,89,.22),rgba(0,0,0,0) 60%);animation:lvu 2.8s ease forwards}\n.lvup small{font-family:'Barlow Condensed';font-size:22px;letter-spacing:6px;color:var(--warm)}.lvup b{font-size:46px;font-weight:800;color:#fff;text-shadow:0 6px 30px rgba(255,178,89,.6)}\n@keyframes lvu{0%{opacity:0;transform:scale(.8)}15%{opacity:1;transform:scale(1.04)}25%{transform:scale(1)}80%{opacity:1}100%{opacity:0}}\n.confetti{position:fixed;inset:0;pointer-events:none;z-index:205;overflow:hidden}.confetti i{position:absolute;top:-12px;width:8px;height:14px;border-radius:2px;animation:cf linear forwards}\n@keyframes cf{to{top:105%;transform:rotate(720deg) translateX(40px)}}\n.mis{background:linear-gradient(180deg,#141d33,#101626);border:1px solid #2c3a5c;border-radius:14px;padding:12px;margin-bottom:16px}\n.mchips{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:10px}.mchip{width:32px;height:32px;border-radius:9px;background:var(--panel2);border:1px solid var(--line);font-size:14px;color:var(--mut)}\n.mchip.on{border-color:var(--warm);color:#fff;box-shadow:0 0 0 1px var(--warm)}.mchip.done{background:#12301f;color:#8ff0b8;border-color:#2e6b4a}\n.mcard b{display:block;font-size:14px;color:#fff}.mcard>span{display:block;font-size:12px;color:var(--mut);margin:2px 0 8px}\n.mbar{height:6px;background:#26314d;border-radius:3px;overflow:hidden;margin-bottom:8px}.mbar i{display:block;height:100%;background:linear-gradient(90deg,#4fd18b,#9ff2c4);transition:width .4s}\n.mg{display:flex;gap:8px;font-size:12.5px;color:#aeb8cc;padding:3px 0}.mg span{width:16px;color:var(--mut2);font-weight:700}.mg.ok{color:#d9f7e6}.mg.ok span{color:var(--ok)}\n.mfoot{display:flex;justify-content:space-between;align-items:center;margin-top:9px}.mfoot .gbtn{padding:6px 12px;font-size:12px}.mxp{font-family:'Barlow Condensed';font-size:15px;color:var(--warm)}.mdone{font-size:12px;color:var(--ok);font-weight:600}\n.mcard.done{opacity:.85}\n.charbtn{display:flex;gap:10px;align-items:center;width:100%;text-align:left;background:linear-gradient(135deg,#17213a,#121a2c);border:1px solid #2c3a5c;border-radius:12px;padding:8px 10px}\n.charbtn:hover{border-color:var(--warm)}.charbtn .cav{width:40px;height:40px;border-radius:10px;overflow:hidden;background:#0d1322;flex:0 0 auto}.charbtn .cav img{width:100%;height:100%;object-fit:cover}.charbtn b{display:block;font-size:13px}.charbtn small{color:var(--mut);font-size:11.5px}\n.mbox.wide{max-width:760px}.mhead{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}.mbox{max-height:84vh;overflow:auto}\n.cgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px;margin:10px 0 14px}\n.ccard{background:linear-gradient(180deg,#18223a,#10172a);border:1px solid var(--line);border-radius:14px;padding:10px;text-align:center;position:relative;transition:transform .15s,border-color .15s}\n.ccard:hover{transform:translateY(-3px);border-color:#4a5d8a}.ccard.on{border-color:var(--warm);box-shadow:0 0 0 1px var(--warm),0 10px 30px -12px rgba(255,178,89,.5)}\n.ccard .cimg{display:block;height:130px;border-radius:10px;overflow:hidden;background:radial-gradient(circle at 50% 30%,#22304f,#0d1322);margin-bottom:8px;padding:14px}\n.ccard .cimg img{width:100%;height:100%;object-fit:cover}.ccard b{display:block;font-size:13px}.ccard small{color:var(--mut);font-size:11.5px}.ccard em{position:absolute;top:8px;right:8px;font-style:normal;font-size:10.5px;background:#0b0f1a;border:1px solid var(--line);border-radius:6px;padding:1px 6px;color:var(--mut)}\n.acont{margin-top:12px}.arow{display:grid;grid-template-columns:48px 1fr 1fr;gap:8px;align-items:end;background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:10px;margin-bottom:8px}\n.arow .acav{width:48px;height:48px;border-radius:10px;overflow:hidden;background:#0d1322;grid-row:span 3}.arow .acav img{width:100%;height:100%;object-fit:cover}\n.af span{display:block;font-size:11px;color:var(--mut);margin-bottom:3px}.arow .minib{grid-column:2 \/ 4;margin-top:0}\n.agrp{font-size:12px;font-weight:700;color:var(--warm);margin:16px 0 6px}\n.prow{display:flex;gap:10px;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:9px;margin-bottom:6px}.prow.focus{border-color:var(--warm)}\n.prow .pv{width:72px;height:72px;border-radius:8px;background:#0d1322;overflow:hidden;flex:0 0 auto}.prow .pv img{width:100%;height:100%;object-fit:cover}\n.pinf{flex:1;display:flex;flex-direction:column;gap:3px;min-width:0}.pinf b{font-size:13px}.pinf span{font-size:12px;color:#b9c3d8}.pinf small{font-size:11px;color:var(--mut)}.pinf input{margin-top:4px}\n.phbox{border:1.5px dashed #34456b;border-radius:12px;padding:18px;display:flex;flex-direction:column;gap:5px;background:repeating-linear-gradient(135deg,#101728,#101728 12px,#121b2f 12px,#121b2f 24px)}\n.phbox b{font-size:14px;color:#fff}.phbox span{font-size:12.5px;color:#b9c3d8}.phbox small{font-size:11.5px;color:var(--mut)}.phbox .gbtn{align-self:flex-start;margin-top:6px;padding:7px 12px;font-size:12px}\n.prof{display:flex;gap:14px;align-items:center;background:linear-gradient(135deg,#1c1406,#141d33);border:1px solid #4a3a18;border-radius:14px;padding:14px}\n.prof .plv{width:56px;height:56px;border-radius:14px;background:linear-gradient(135deg,#ffb259,#ff7a3d);color:#1a1006;font-family:'Barlow Condensed';font-size:34px;font-weight:700;display:flex;align-items:center;justify-content:center}\n.prof b{display:block;font-size:18px}.prof span{font-size:12.5px;color:#e8c89a}\n.bgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.badge{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:10px 6px;text-align:center;opacity:.45}\n.badge span{display:block;font-size:22px}.badge b{font-size:11px;font-weight:600}.badge.on{opacity:1;border-color:#2e6b4a;background:#10231a}.badge.on span{color:var(--ok)}\n.lvlist{display:flex;flex-direction:column;gap:4px}.lvi{display:flex;gap:10px;align-items:center;font-size:13px;color:var(--mut);padding:5px 8px;border-radius:8px}.lvi span{font-family:'Barlow Condensed';font-size:16px;width:20px}.lvi small{margin-left:auto;font-size:11px}.lvi.on{color:#fff;background:#141d33}.lvi.on span{color:var(--warm)}\n@media(max-width:760px){.player .pinfo{display:none}.bgrid{grid-template-columns:repeat(2,1fr)}.arow{grid-template-columns:1fr}.arow .acav{display:none}.arow .minib{grid-column:auto}}\n.sim.side{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:0 18px;align-items:start}\n.sim.side #expoCv{grid-column:1;grid-row:1 \/ span 6;width:100%;height:auto;max-height:78vh;object-fit:contain}\n.sim.side #expoCv{order:0}.sim.side .simrow{order:1;grid-template-columns:1fr;margin-top:0}.sim.side #expoVer{order:2;margin-top:0}.sim.side #expoRead{order:3}.sim.side #expoHist{order:4;margin-top:12px}\n#cmpCv{max-height:74vh;width:auto;max-width:100%;margin:0 auto}\n.figrow.one{grid-template-columns:1fr;max-width:420px}\n.coach{display:flex;gap:10px;align-items:flex-end;background:linear-gradient(135deg,#1c1406,#141d33);border:1px solid #4a3a18;border-radius:14px;padding:10px 10px 0 4px;margin:0 2px 14px;overflow:hidden}\n.coach img{width:74px;height:auto;display:block;flex:0 0 auto}.coach div{padding-bottom:10px}.coach b{display:block;font-size:13px;color:#fff}.coach span{font-size:11.5px;color:#e8c89a;line-height:1.45}\n.prof .pav{width:64px;height:64px;object-fit:cover;object-position:top;border-radius:14px;background:#0d1322}\n.prow .pv.def{outline:2px solid #2e6b4a}\n@media(max-width:760px){.sim.side{grid-template-columns:1fr}.sim.side #expoCv{grid-row:auto}}\n.clist{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}\n.citem{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:4px 4px 6px;text-align:center;min-width:0;transition:border-color .15s,transform .15s}\n.citem:hover{border-color:#4a5d8a;transform:translateY(-2px)}.citem.on{border-color:var(--warm);box-shadow:0 0 0 1px var(--warm)}\n.citem .ct{display:block;position:relative;aspect-ratio:4\/5;border-radius:7px;overflow:hidden;background:radial-gradient(circle at 50% 35%,#24324f,#0d1322);margin-bottom:4px}\n.citem .ct img{width:100%;height:100%;object-fit:cover;display:block}.citem .ct svg{width:70%;height:70%;margin:15%}\n.citem .ct.mix{display:grid;grid-template-columns:1fr 1fr}.citem .ct.mix img,.citem .ct.mix svg{width:100%;height:100%;margin:0;object-fit:cover}\n.citem b{display:block;font-size:10.5px;font-weight:600;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.citem .cload,.citem .cerr{position:absolute;left:0;right:0;bottom:0;font-style:normal;font-size:10px;background:rgba(0,0,0,.7);color:#ffd699;padding:2px 0;font-family:'Barlow Condensed'}.citem .cerr{color:#ff9a9a}\n.citem.add .ct{display:flex;align-items:center;justify-content:center;font-size:24px;color:var(--blue-l)}\n.facefix{display:flex;gap:4px;flex-wrap:wrap;margin-top:8px}.facefix span{font-size:11.5px;color:var(--mut);width:100%}.facefix button{flex:1;background:var(--panel2);border:1px solid var(--line);border-radius:7px;padding:5px 0;font-size:11.5px;font-weight:600}.facefix button:hover{border-color:var(--warm)}\n.lb.dim.rot{background:rgba(255,178,89,.92);color:#1a1006}\n.bdsw{display:grid;grid-template-columns:repeat(10,1fr);gap:5px;margin-top:8px}\n.bds{aspect-ratio:1;border-radius:50%;border:2px solid rgba(255,255,255,.14);padding:0;cursor:pointer;min-width:0}\n.bds:hover{transform:scale(1.12)}.bds.on{border-color:var(--warm);box-shadow:0 0 0 2px var(--warm)}\ninput.bds.pick{width:100%;height:auto;padding:0;background:conic-gradient(red,yellow,lime,cyan,blue,magenta,red);border-radius:50%;overflow:hidden}\n.pip{position:absolute;right:274px;bottom:12px;width:214px;z-index:5;display:flex;flex-direction:column;gap:0;pointer-events:none}\n.pip>*{pointer-events:auto}.pip.min{display:none!important}\n.piphead{display:flex;justify-content:space-between;align-items:center;background:rgba(10,15,28,.94);border:1px solid var(--line);border-bottom:none;border-radius:12px 12px 0 0;padding:5px 9px;font-size:11.5px;font-weight:700}\n.piphead button{background:none;border:none;color:var(--mut);font-size:16px;line-height:1;padding:0 2px}\n.pipinfo{background:rgba(10,15,28,.94);border-left:1px solid var(--line);border-right:1px solid var(--line);padding:0 9px 5px;font-size:11px;color:var(--warm);font-family:'Barlow Condensed';font-size:13px}\n.pipframe{position:relative;width:200px;margin:0;border:7px solid rgba(10,15,28,.94);border-top:none;border-bottom:none;box-sizing:content-box;outline:1px solid rgba(255,255,255,.4);outline-offset:-1px;cursor:zoom-in;background:transparent}\n.pipframe .g{position:absolute;background:rgba(255,255,255,.3)}\n.pipctl{background:rgba(10,15,28,.94);border:1px solid var(--line);border-top:none;border-radius:0 0 12px 12px;padding:6px 7px 7px}\n.pipfoc{display:flex;gap:2px;margin-bottom:5px}.pipfoc button{flex:1;background:var(--panel2);border:1px solid var(--line);border-radius:6px;padding:4px 0;font-family:'Barlow Condensed';font-size:12.5px;font-weight:600;color:var(--mut);min-width:0}\n.pipfoc button.on{background:var(--warm);border-color:var(--warm);color:#1a1006}\n.pipcam{display:flex;gap:3px;align-items:center;margin-top:3px}.pipcam span{flex:1;text-align:center;font-family:'Barlow Condensed';font-size:13px;color:#fff;white-space:nowrap}\n.pipcam button{background:var(--panel2);border:1px solid var(--line);border-radius:6px;padding:4px 7px;font-size:11px;font-weight:600}.pipcam button:hover,.pipfoc button:hover{border-color:var(--warm)}\n.pipopen{position:absolute;right:274px;bottom:12px;z-index:5;display:none;background:rgba(10,15,28,.94);border:1px solid var(--line);border-radius:10px;padding:7px 12px;font-size:12px;font-weight:700}\n@media(max-width:1000px){.pip,.pipopen{right:214px}}\n@media(max-width:1180px){.hud .hint{display:none}}\n.gelsw{display:grid;grid-template-columns:repeat(10,1fr);gap:4px}\n.gel{aspect-ratio:1;border-radius:50%;border:2px solid rgba(255,255,255,.14);padding:0;min-width:0;font-size:11px;color:var(--mut);background:var(--panel2)}\n.gel.on{border-color:#fff;box-shadow:0 0 0 2px var(--warm)}.gel:hover{transform:scale(1.12)}\ninput.gel.pick{width:100%;height:auto;padding:0;background:conic-gradient(red,yellow,lime,cyan,blue,magenta,red);overflow:hidden}\n.geld{display:inline-block;width:9px;height:9px;border-radius:50%;margin-left:5px;vertical-align:middle;border:1px solid rgba(255,255,255,.4)}\n.pipsz{display:flex;gap:2px;margin-left:auto;margin-right:6px}.pipsz button{background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:1px 6px;font-size:10.5px;font-weight:600;color:var(--mut)}.pipsz button.on{color:#1a1006;background:var(--warm);border-color:var(--warm)}\n.pipframe{box-shadow:0 0 0 1px rgba(255,178,89,.35)}\n.lbody{padding:34px 48px 80px}\n.lwrap .lead{max-width:80ch}\n.cards{grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}\n.gl{grid-template-columns:repeat(auto-fill,minmax(320px,1fr))}\n.figrow{max-width:1100px}.figrow.three{max-width:1300px}\n.sim.side{grid-template-columns:minmax(0,1.25fr) minmax(320px,1fr);gap:0 26px}\n.sim.side #expoCv{max-height:82vh}\n.sqc{max-width:640px}\n.tbl{max-width:1100px}\n.pipasp{display:flex;gap:2px;margin-bottom:5px}.pipasp button{flex:1;background:var(--panel2);border:1px solid var(--line);border-radius:6px;padding:3px 0;font-family:'Barlow Condensed';font-size:12px;font-weight:600;color:var(--mut);min-width:0}.pipasp button.on{background:#e9eef7;border-color:#e9eef7;color:#0a0f1c}.pipasp button:hover{border-color:var(--warm)}\n.grip{position:absolute;left:0;top:0;width:18px;height:18px;cursor:nwse-resize;z-index:3;border-top-left-radius:12px;background:linear-gradient(135deg,var(--warm) 0 22%,transparent 22%)}\n.grip:hover{background:linear-gradient(135deg,#fff 0 26%,transparent 26%)}\n.piphead{position:relative;padding-left:22px}.planbox .pt{left:24px}\nhtml.kb-embed,html.kb-embed body{overflow:auto!important;height:auto!important}\n.planbox{display:flex;flex-direction:column}.planbox canvas{flex:1;min-height:0;height:auto!important}.planbox.min canvas{display:none}\n.planhead{position:relative;display:flex;align-items:center;gap:6px;padding:5px 9px 5px 24px;font-size:11.5px;font-weight:700;border-bottom:1px solid var(--line);cursor:move;user-select:none;flex:0 0 auto}\n.planhead small{color:var(--mut);font-weight:500}.planhead button{margin-left:auto;background:none;border:none;color:var(--mut);font-size:16px;line-height:1;padding:0 2px}\n.piphead{cursor:move;user-select:none}.planhead.dragging,.piphead.dragging{cursor:grabbing;background:#1a2440}\n.pipcam.aim{justify-content:center}.pipcam.aim button{min-width:34px}\n#pipA{font-size:12px}\n.lwrap{max-width:none}.lbody{padding:30px 40px 80px}\n.lwrap p,.lwrap .lead{max-width:120ch}.tbl{max-width:none}.figrow{max-width:1400px}\n.sim.side #expoCv{max-height:84vh}\n.les .ic{color:#9fb0cf}.les.on .ic{color:#fff;background:#2a4a8f}.les:hover .ic{color:#fff}\n.sqc{max-width:min(560px,100%);max-height:78vh;width:auto!important;margin:0 auto;object-fit:contain}\n.card.hasimg img{height:auto!important;aspect-ratio:4\/5;object-fit:cover;object-position:50% 20%}\n.lwrap>figure.fig{max-width:1100px}.lwrap>figure.fig img{max-height:70vh;object-fit:contain;width:auto;max-width:100%}\n.figrow .fig img{aspect-ratio:auto}\n\/* ===== learning layout polish ===== *\/\n.mlesbar,.railx{display:none}\n.lwrap{max-width:1320px}\n.lwrap p,.lwrap .lead{max-width:78ch}\n.tbl{max-width:1000px}\n.figrow{max-width:1000px}.figrow.three{max-width:1180px}.figrow.one{max-width:460px}\n.lwrap>figure.fig{max-width:900px}\n.sim canvas{max-width:1000px}\n.sim.side{grid-template-columns:auto minmax(320px,440px);justify-content:start;gap:0 28px}\n.sim.side #expoCv{width:auto;height:calc(100vh - 250px);max-height:880px;min-height:420px;max-width:100%;background:transparent;border-radius:12px}\n#histImg.sqc{width:auto!important;height:calc(100vh - 330px);min-height:380px;max-height:820px;background:transparent}\n#cmpCv{height:calc(100vh - 330px);min-height:360px;width:auto;max-width:100%;background:transparent}\n.cards{grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px}\n.card.sc{padding:0;overflow:hidden;display:flex;flex-direction:column}\n.scm{position:relative;aspect-ratio:1\/1;background:#0d1322;border-bottom:1px solid var(--line)}\n.scm img{width:100%;height:100%;object-fit:cover;object-position:50% 18%;display:block}\n.scm svg{width:100%;height:100%;display:block}\n.scm .tagd{position:absolute;left:8px;top:8px;font-size:10.5px;font-weight:700;color:var(--mut);background:rgba(10,15,28,.85);border:1px solid var(--line);border-radius:6px;padding:2px 7px}\n.scb{padding:12px 14px 14px;display:flex;flex-direction:column;flex:1}.scb p{flex:1;font-size:12.8px}\n.pbtn.sm{padding:8px 12px;font-size:12.5px;width:100%}\n@media(max-width:760px){\n .top{height:auto;flex-wrap:wrap;padding:8px 12px;gap:8px;position:sticky;top:0;z-index:40}\n .brand img{height:15px}.brand span{display:none}\n .player{margin-left:auto;padding:3px}.player .lv{width:28px;height:28px;font-size:17px}\n #btnAssets{display:none}\n .tabs{order:3;width:100%;margin:0}.tab{flex:1;padding:8px 6px;font-size:12.5px;white-space:nowrap}\n .tacts{order:4;width:100%;margin:0;flex-wrap:wrap}\n #pLearn.pane.on{display:block}\n .mlesbar{display:flex;gap:6px;position:sticky;top:96px;z-index:30;background:rgba(10,15,28,.96);backdrop-filter:blur(6px);padding:8px 12px;border-bottom:1px solid var(--line)}\n .mlesbar button{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:9px 12px;font-size:13px;font-weight:700}\n #mLesBtn{flex:1;display:flex;gap:8px;align-items:center;text-align:left;min-width:0}#mLesBtn #mLesTxt{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n #mPrev,#mNext{width:44px;font-size:20px;padding:4px 0}\n .rail{display:none;border:none}\n .rail.open{display:block;position:fixed;inset:0;z-index:90;width:100%;max-width:none;padding:14px 14px 40px;overflow-y:auto;background:var(--panel)}\n .railx{display:block;margin:0 0 12px auto;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:8px 14px;font-weight:700;font-size:13px}\n .coach img{width:56px}\n body.noscroll{overflow:hidden!important}\n .lbody{padding:16px 14px 60px;overflow:visible}\n .lwrap h1{font-size:25px;line-height:1.2}.lwrap .lead{font-size:15px}.lwrap h2{font-size:17px}\n .sim{padding:10px;border-radius:12px}\n .sim.side{display:block}.sim.side #expoCv,#histImg.sqc,#cmpCv{height:auto!important;width:100%!important;max-height:none!important;min-height:0}\n .simrow,.simrow.two{grid-template-columns:1fr;gap:4px}\n .tbl{display:block;overflow-x:auto;font-size:12.5px}.tbl td,.tbl th{padding:7px 6px;min-width:96px}\n .figrow,.figrow.three{grid-template-columns:1fr 1fr;gap:8px}.fig figcaption{font-size:11.5px}\n .cards{grid-template-columns:1fr}\n .lnav{flex-direction:column;align-items:stretch;gap:10px}.lnl{justify-content:space-between}.lnav .pbtn{width:100%}\n .exbox{padding:12px}\n .gl{grid-template-columns:1fr}\n}\n.scm .tagd{top:auto;bottom:8px}\n.scm.ph img{height:100%!important;aspect-ratio:auto!important}\n@media(max-width:760px){\n .card.sc{flex-direction:row;align-items:stretch}\n .card.sc .scm{width:118px;flex:0 0 118px;aspect-ratio:auto;border-bottom:none;border-right:1px solid var(--line)}\n .card.sc .scm .tagd{display:none}\n .scb{padding:10px 12px 12px}.scb h3{font-size:14.5px;margin-bottom:4px}.scb p{font-size:12.3px;margin-bottom:8px}\n}\n.scm{overflow:hidden}.scm.ph img{position:absolute;inset:0;width:100%;height:100%!important}\n@media(max-width:1000px){.sp{width:250px;min-width:230px}.sp.r{width:270px}.meter{width:200px}.meter .big{font-size:40px}.planbox{width:190px;height:190px}.vbar{left:222px}.hud{right:214px}}\n@media(max-width:760px){body{overflow:auto}.pane.on{flex-direction:column;height:auto}.rail,.sp,.sp.r{width:100%;max-width:none;border:none;border-bottom:1px solid var(--line)}.view{height:70vh}.lbody{padding:24px 18px}.simrow{grid-template-columns:1fr}.cards{grid-template-columns:1fr}.brand span{display:none}}\n@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n<\/style>\n<\/head>\n<body>\n<div class=\"top\">\n  <div class=\"brand\"><img id=\"logo\" alt=\"K-BLACK\"><span>Photo Lab<\/span><\/div>\n  <button class=\"player\" id=\"player\" title=\"H\u1ed3 s\u01a1 ng\u01b0\u1eddi ch\u01a1i\"><span class=\"lv\" id=\"pLv\">1<\/span><span class=\"pinfo\"><b id=\"pName\">T\u00e2n binh<\/b><span class=\"xpbar\"><i id=\"pXp\"><\/i><\/span><small id=\"pXpTxt\">0 XP<\/small><\/span><\/button>\n  <div class=\"tabs\">\n    <button class=\"tab on\" data-t=\"learn\">H\u1ecdc nhi\u1ebfp \u1ea3nh<\/button>\n    <button class=\"tab\" data-t=\"studio\">Studio \u00e1nh s\u00e1ng 3D<\/button>\n  <\/div>\n  <button class=\"tbtn\" id=\"btnAssets\" style=\"margin-left:8px\">T\u00e0i nguy\u00ean<\/button>\n  <div class=\"tacts\" id=\"studioActs\" style=\"display:none\">\n    <button class=\"tbtn ic\" id=\"btnUndo\" title=\"Ho\u00e0n t\u00e1c (Ctrl+Z)\" aria-label=\"Ho\u00e0n t\u00e1c\" disabled>\u21b6<\/button>\n    <button class=\"tbtn ic\" id=\"btnRedo\" title=\"L\u00e0m l\u1ea1i (Ctrl+Shift+Z)\" aria-label=\"L\u00e0m l\u1ea1i\" disabled>\u21b7<\/button>\n    <button class=\"tbtn\" id=\"btnKeys\">Ph\u00edm t\u1eaft<\/button>\n    <button class=\"tbtn\" id=\"btnSaveSet\">L\u01b0u setup<\/button>\n    <button class=\"tbtn\" id=\"btnMySet\">Setup \u0111\u00e3 l\u01b0u<\/button>\n  <\/div>\n<\/div>\n\n<!-- LEARN -->\n<div class=\"pane on\" id=\"pLearn\">\n  <div class=\"mlesbar\" id=\"mLesBar\"><button id=\"mLesBtn\" aria-label=\"Danh s\u00e1ch b\u00e0i h\u1ecdc\"><span class=\"mi\">\u2630<\/span><span id=\"mLesTxt\">B\u00e0i h\u1ecdc<\/span><\/button><button id=\"mPrev\" aria-label=\"B\u00e0i tr\u01b0\u1edbc\">\u2039<\/button><button id=\"mNext\" aria-label=\"B\u00e0i ti\u1ebfp\">\u203a<\/button><\/div>\n  <nav class=\"rail\" id=\"rail\"><button class=\"railx\" id=\"railX\" aria-label=\"\u0110\u00f3ng danh s\u00e1ch\">\u2715 \u0110\u00f3ng<\/button>\n    <div class=\"coach\"><img alt=\"PHOTO LAB \u2013 K-BLACK Studio\" id=\"coachImg\"><div><b>Tr\u1ee3 l\u00fd K-BLACK<\/b><span>H\u1ecdc xong m\u1ed7i b\u00e0i +40 XP. V\u00e0o Studio 3D l\u00e0m nhi\u1ec7m v\u1ee5 \u0111\u1ec3 l\u00ean c\u1ea5p.<\/span><\/div><\/div>\n    <div class=\"prog\"><small id=\"progTxt\">0\/10 b\u00e0i \u0111\u00e3 h\u1ecdc<\/small><div class=\"bar\"><i id=\"progBar\"><\/i><\/div><\/div>\n    <div id=\"lesList\"><\/div>\n  <\/nav>\n  <main class=\"lbody\" id=\"lBody\"><div class=\"lwrap\" id=\"lWrap\"><\/div><\/main>\n<\/div>\n\n<!-- STUDIO -->\n<div class=\"pane\" id=\"pStudio\">\n  <aside class=\"sp\" id=\"spLeft\"><\/aside>\n  <section class=\"view\">\n    <div id=\"view3d\"><\/div>\n    <div class=\"nogl\" id=\"noGL\">Tr\u00ecnh duy\u1ec7t ch\u01b0a t\u1ea3i \u0111\u01b0\u1ee3c th\u01b0 vi\u1ec7n 3D. Ki\u1ec3m tra k\u1ebft n\u1ed1i m\u1ea1ng r\u1ed3i t\u1ea3i l\u1ea1i trang.<\/div>\n    <div class=\"povframe\" id=\"povFrame\"><\/div>\n    <div class=\"vbar\">\n      <div class=\"vgrp\"><button data-m=\"orbit\" class=\"on\" title=\"Ph\u00edm 1\">Xoay t\u1ef1 do<\/button><button data-m=\"pov\" title=\"Ph\u00edm 2\">Qua \u1ed1ng k\u00ednh<\/button><button data-m=\"top\" title=\"Ph\u00edm 3\">Nh\u00ecn t\u1eeb tr\u00ean<\/button><\/div>\n      <div class=\"vgrp\"><button data-v=\"dims\" title=\"Ph\u00edm D\">Kho\u1ea3ng c\u00e1ch<\/button><button data-v=\"marks\" title=\"Ph\u00edm X\">D\u1ea5u X<\/button><button data-v=\"tags\">T\u00ean \u0111\u00e8n<\/button><\/div>\n      <div class=\"vgrp\"><button id=\"btnReset\">C\u0103n g\u00f3c<\/button><button id=\"btnOrient\" title=\"\u0110\u1ed5i m\u00e1y d\u1ecdc \/ ngang\">M\u00e1y d\u1ecdc<\/button><button id=\"btnShot\">Ch\u1ee5p \u1ea3nh<\/button><button id=\"btnDiag\">S\u01a1 \u0111\u1ed3 \u0111\u00e8n<\/button><\/div>\n    <\/div>\n    <div class=\"labels\" id=\"labels\"><\/div>\n    <div class=\"hud\" id=\"hud\"><\/div>\n    <div class=\"meter\" id=\"meter\"><\/div>\n    <div class=\"pip\" id=\"pip\"><div class=\"piphead\"><span class=\"grip\" id=\"gripPip\" title=\"K\u00e9o \u0111\u1ec3 \u0111\u1ed5i c\u1ee1\"><\/span><span>Qua \u1ed1ng k\u00ednh<\/span><span class=\"pipsz\" id=\"pipSz\"><\/span><button id=\"pipMin\" title=\"Thu nh\u1ecf\" aria-label=\"Thu nh\u1ecf m\u00e0n \u1ed1ng k\u00ednh\">\u2013<\/button><\/div><div class=\"pipinfo\" id=\"pipInfo\"><\/div>\n      <div class=\"pipframe\" id=\"pipFrame\" title=\"B\u1ea5m \u0111\u1ec3 xem to\u00e0n m\u00e0n h\u00ecnh\"><div class=\"g\" style=\"left:33.33%;top:0;bottom:0;width:1px\"><\/div><div class=\"g\" style=\"left:66.66%;top:0;bottom:0;width:1px\"><\/div><div class=\"g\" style=\"top:33.33%;left:0;right:0;height:1px\"><\/div><div class=\"g\" style=\"top:66.66%;left:0;right:0;height:1px\"><\/div><\/div>\n      <div class=\"pipctl\"><div class=\"pipfoc\" id=\"pipFoc\"><\/div><div class=\"pipasp\" id=\"pipAsp\"><\/div><div class=\"pipcam\"><button data-c=\"hdn\" title=\"H\u1ea1 m\u00e1y 10 cm\">\u25bc H\u1ea1<\/button><span id=\"pipH\"><\/span><button data-c=\"hup\" title=\"N\u00e2ng m\u00e1y 10 cm\">\u25b2 N\u00e2ng<\/button><\/div><div class=\"pipcam\"><button data-c=\"near\" title=\"Ti\u1ebfn 25 cm\">Ti\u1ebfn<\/button><span id=\"pipD\"><\/span><button data-c=\"far\" title=\"L\u00f9i 25 cm\">L\u00f9i<\/button><button data-c=\"orient\" id=\"pipOri\" title=\"\u0110\u1ed5i khung d\u1ecdc \/ ngang\">D\u1ecdc<\/button><\/div><div class=\"pipcam aim\"><button data-c=\"pl\" title=\"Ng\u1eafm sang tr\u00e1i 2\u00b0\">\u25c0<\/button><button data-c=\"tu\" title=\"Ng\u1eafm l\u00ean 2\u00b0\">\u25b2<\/button><button data-c=\"aim0\" title=\"Ng\u1eafm l\u1ea1i v\u00e0o m\u1eb7t\">\u2299<\/button><button data-c=\"td\" title=\"Ng\u1eafm xu\u1ed1ng 2\u00b0\">\u25bc<\/button><button data-c=\"pr\" title=\"Ng\u1eafm sang ph\u1ea3i 2\u00b0\">\u25b6<\/button><\/div><div class=\"pipcam\"><button data-c=\"orl\" title=\"\u0110i v\u00f2ng sang tr\u00e1i 10\u00b0\">\u21ba V\u00f2ng<\/button><span id=\"pipA\"><\/span><button data-c=\"orr\" title=\"\u0110i v\u00f2ng sang ph\u1ea3i 10\u00b0\">V\u00f2ng \u21bb<\/button><\/div><\/div><\/div>\n    <button class=\"pipopen\" id=\"pipOpen\">Qua \u1ed1ng k\u00ednh<\/button>\n    <div class=\"planbox\" id=\"planBox\"><div class=\"planhead\" id=\"planHead\"><span class=\"grip\" id=\"gripPlan\" title=\"K\u00e9o \u0111\u1ec3 \u0111\u1ed5i c\u1ee1\"><\/span><span>M\u1eb7t b\u1eb1ng<\/span><small>k\u00e9o \u0111\u00e8n \u0111\u1ec3 \u0111\u1eb7t<\/small><button id=\"planMin\" title=\"Thu g\u1ecdn\" aria-label=\"Thu g\u1ecdn m\u1eb7t b\u1eb1ng\">\u2013<\/button><\/div><canvas id=\"plan\" width=\"500\" height=\"500\"><\/canvas><\/div>\n  <\/section>\n  <aside class=\"sp r\" id=\"spRight\"><\/aside>\n<\/div>\n\n<div class=\"modal\" id=\"setModal\"><div class=\"mbox\"><div style=\"display:flex;justify-content:space-between;align-items:center\"><b>Setup \u0111\u00e3 l\u01b0u<\/b><button class=\"tbtn\" id=\"setClose\">\u0110\u00f3ng<\/button><\/div><div id=\"setList\"><\/div><\/div><\/div>\n<div class=\"modal\" id=\"keyModal\"><div class=\"mbox\"><div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:10px\"><b>Ph\u00edm t\u1eaft trong Studio<\/b><button class=\"tbtn\" id=\"keyClose\">\u0110\u00f3ng<\/button><\/div>\n<table class=\"tbl\"><tr><td>K\u00e9o \u0111\u00e8n \/ ch\u1ee7 th\u1ec3 \/ m\u00e1y<\/td><td>Di chuy\u1ec3n tr\u00ean s\u00e0n<\/td><\/tr><tr><td>Shift + k\u00e9o \u0111\u00e8n<\/td><td>N\u00e2ng h\u1ea1 \u0111\u1ed9 cao<\/td><\/tr><tr><td>\u2190 \u2192<\/td><td>Xoay g\u00f3c \u0111\u00e8n 5\u00b0 (Shift: 25\u00b0)<\/td><\/tr><tr><td>\u2191 \u2193<\/td><td>Xa \/ g\u1ea7n 5 cm (Shift: 25 cm)<\/td><\/tr><tr><td>[ ]<\/td><td>H\u1ea1 \/ n\u00e2ng 5 cm<\/td><\/tr><tr><td>Tab<\/td><td>Ch\u1ecdn \u0111\u00e8n k\u1ebf ti\u1ebfp<\/td><\/tr><tr><td>Delete<\/td><td>Xo\u00e1 \u0111\u00e8n \u0111ang ch\u1ecdn<\/td><\/tr><tr><td>1 \u00b7 2 \u00b7 3<\/td><td>Xoay t\u1ef1 do \u00b7 qua \u1ed1ng k\u00ednh \u00b7 nh\u00ecn t\u1eeb tr\u00ean<\/td><\/tr><tr><td>D \u00b7 X<\/td><td>B\u1eadt t\u1eaft kho\u1ea3ng c\u00e1ch \u00b7 d\u1ea5u X<\/td><\/tr><tr><td>Ctrl + Z<\/td><td>Ho\u00e0n t\u00e1c<\/td><\/tr><\/table>\n<p class=\"note\">B\u1ea5m v\u00e0o con s\u1ed1 c\u1ee7a b\u1ea5t k\u1ef3 thanh tr\u01b0\u1ee3t n\u00e0o \u0111\u1ec3 g\u00f5 gi\u00e1 tr\u1ecb ch\u00ednh x\u00e1c.<\/p><\/div><\/div>\n<div class=\"dragtip\" id=\"dragTip\"><\/div>\n<div class=\"msg\" id=\"msg\"><\/div>\n\n<!--KBFPF-->\n<script>\n(function(){try{var P=window.CanvasRenderingContext2D&&CanvasRenderingContext2D.prototype;if(!P)return;var force=\/[?&]kbpf=1\/.test(location.search);if(('filter' in P)&&!force)return;\nvar od=P.drawImage,os=P.save,or=P.restore;\nfunction parse(v){var o={b:1,bl:0};String(v||'').replace(\/brightness\\(([\\d.]+)(%?)\\)\/g,function(_,x,p){o.b*=p?x\/100:+x});String(v||'').replace(\/blur\\(([\\d.]+)px\\)\/g,function(_,x){o.bl+=+x});return o}\nObject.defineProperty(P,'filter',{configurable:true,get:function(){return this.__kf||'none'},set:function(v){this.__kf=v;this.__ko=parse(v)}});\nP.save=function(){(this.__ks||(this.__ks=[])).push(this.__kf);return os.apply(this,arguments)};\nP.restore=function(){if(this.__ks&&this.__ks.length){var v=this.__ks.pop();this.__kf=v;this.__ko=parse(v)}return or.apply(this,arguments)};\nvar T1=document.createElement('canvas'),T2=document.createElement('canvas');\nP.drawImage=function(img){var o=this.__ko;if(!o||(o.b===1&&!o.bl))return od.apply(this,arguments);\n var a=arguments,sx,sy,sw,sh,dx,dy,dw,dh,iw=img.naturalWidth||img.videoWidth||img.width,ih=img.naturalHeight||img.videoHeight||img.height;\n if(a.length>=9){sx=a[1];sy=a[2];sw=a[3];sh=a[4];dx=a[5];dy=a[6];dw=a[7];dh=a[8]}else{sx=0;sy=0;sw=iw;sh=ih;dx=a[1];dy=a[2];dw=a.length>=5?a[3]:iw;dh=a.length>=5?a[4]:ih}\n if(!dw||!dh||!sw||!sh)return;\n var pad=Math.ceil(o.bl*2),W=Math.max(1,Math.ceil(Math.abs(dw))+pad*2),H=Math.max(1,Math.ceil(Math.abs(dh))+pad*2);\n if(W*H>16e6)return od.apply(this,arguments);\n T1.width=W;T1.height=H;var c=T1.getContext('2d');c.clearRect(0,0,W,H);\n if(o.bl>0.3){var r=o.bl,taps=[[0,0]];for(var k=0;k<8;k++){var an=k*Math.PI\/4;taps.push([Math.cos(an)*r*.6,Math.sin(an)*r*.6]);taps.push([Math.cos(an+.39)*r*1.2,Math.sin(an+.39)*r*1.2])}\n   for(var i=0;i<taps.length;i++){c.globalAlpha=1\/(i+1);od.call(c,img,sx,sy,sw,sh,pad+taps[i][0],pad+taps[i][1],dw,dh)}c.globalAlpha=1}\n else od.call(c,img,sx,sy,sw,sh,pad,pad,dw,dh);\n if(o.b<1){c.globalCompositeOperation='source-atop';c.fillStyle='rgba(0,0,0,'+(1-o.b)+')';c.fillRect(0,0,W,H)}\n else if(o.b>1){T2.width=W;T2.height=H;var c2=T2.getContext('2d');od.call(c2,T1,0,0);c.globalCompositeOperation='lighter';var rr=o.b-1;while(rr>0.001){c.globalAlpha=Math.min(1,rr);od.call(c,T2,0,0);rr-=1}}\n c.globalCompositeOperation='source-over';c.globalAlpha=1;\n od.call(this,T1,dx-pad,dy-pad,W,H)}\n}catch(e){}})();\n<\/script>\n<!--\/KBFPF-->\n<script>window.KB_ASSETS={headUrl:\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-head.glb\",colUrl:\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-head-col.jpg\",nrmUrl:\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-head-nrm.jpg\"};\nwindow.KB_PHOTOS={\"wb_warm\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-wb-warm.jpg\",\"wb_ok\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-wb-ok.jpg\",\"light_soft\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-light-soft.jpg\",\"sh_freeze\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-sh-freeze.jpg\",\"sh_blur\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-sh-blur.jpg\",\"light_hard\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-light-hard.jpg\",\"setup_clamshell\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-setup-clamshell.jpg\",\"setup_lowkey\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-setup-lowkey.jpg\",\"pose_2\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-pose-2.jpg\",\"ap_shallow\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-ap-shallow.jpg\",\"ap_deep\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-ap-deep.jpg\",\"iso_low\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-iso-low.jpg\",\"dark_event\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-dark-event.jpg\",\"iso_high\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-iso-high.jpg\",\"focal_wide\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-focal-wide.jpg\",\"focal_tele\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-focal-tele.jpg\",\"white\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-white.jpg\",\"portrait\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-portrait.jpg\",\"golden\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-golden.jpg\",\"openshade\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-openshade.jpg\",\"mascot\":\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-mascot.webp\"};\nwindow.KB_EXPO={w:720,h:960,subj:\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-subj.webp\",levels:[\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-0.jpg\",\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-1.jpg\",\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-2.jpg\",\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-3.jpg\",\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-4.jpg\",\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-5.jpg\",\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-6.jpg\",\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-7.jpg\",\"\/wp-content\/uploads\/2026\/10\/kblack-photolab-expo-8.jpg\"]};\n<\/script>\n<script>\n\"use strict\";\nconst LOGO='data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaQAAABNCAYAAADpcBDLAAApyElEQVR42u2dd5ikVZX\/P6e6ZoYgCIMESRJFkoAISFYQUREMsCZUEEEEAQm7YgBFXBPmnxL8uStgWFEJrqIgSBIREEQYgmQQYcg5DEx31dk\/7jnUpeiurvfeW93VPXWf5316pmfqrfe99+TwPcJgdVyqWhOR5mAn+uIshvyPdiEiOtiZwUqgJQEkkJA0ot\/PAJa2a0lgCFgBWA4YBmpAA7gDeBJ4HHgMuE9Enm6jVQV0QKPdL+nBQdejg8w9CLX7zAcemeiDVVUREVXVlwH1Au\/TaTXtO2oico9\/92QrY2C2ncFk0+mwiDw8hmCpxUIl4T0XA15igkYSaXSeiDw2jYT1bGCG0aUUPMenReTJSaZpYiNTVVcFtgQ2BF4FvMKuxbq45TzgAeA24GbgGuACEbmpXTnlGLYmV5cqIE8fE5H5BegDk1dLAyMZNKLRZx+SggddF5ERVX0n8G37Es0k5hFjirNEZF9VHcoRPBXfZ4aIDKvqXsDneqXA2w5FgE+IyBmT6ZlFing2cKZZiNrD9+9GkDWAR4E7gb8BFwDXunBLYfroPb8I7GEWcL3iszXsM2cD+4lIox+MiZxogKquAJwGLG\/vVytkcNWAG0TkLZOxRy6j7M9LALsAHwTWsXcd7WzHonuNhHL7uh+4ATgR+HVMo1XlV0Sj6wG\/NnmYKl\/mAXuJyF9SZWmkjAQ4CXiD8U2q0dqwdzoW+Fq9B+f+VrMuSq57eqwQRmPMYVXdHvgmsMQE8cxhpoykT8KEdWBVC1f0w1oF2Ah4p\/39FlU93Zj+slioVrzvMsBKmc+2\/DRwjoZMcWwObNaj71hKVVcXkdsmyuhyIWoG84rA7sD+wMpt\/3XYZEzNfnYjZDW6mvaZZe16A3CHqn4DOEVEHsl454WA1TO3ogEskmscmtGyqynzEute4BQKWT4uBEbMon6NHcyw\/Uy9GvbzKeD0yMqaCCuqqapbAT8zZTSS+S6drhH76q+KyLc8pNAvRrNZVfF59MPl1umawOHA+ar6Y1XdyM5OIkuum+W0Oj\/hWeLPTvlonf3cyP48v\/C5NYCFge3se2oTxM9qXsa+wB+Br5oy0jaammFGWK2C8esKbMg+X2u756pm\/Z+jqju5MqpIny77ns2UpfNyZKgbyqq6lBnqmikXXPZ9QkTuBKQUQUgkIDawv\/vB5l7\/EpHrJsJrMDd2RFU3NCW4LFFupweX3\/s44EhTRv2WBK314SWRAB0xIfdB4EJVPYyQU9IKTC8Fn2lqaqLAXyOquhCwcaE9GY3ea8CmExHxiAzlpVX1NOAEYC0zIrTtHaUHPCMRjW4MnK6qn3clmaCUSpxBlgdtz3yEKXT3CFOeQ032\/VpEfuWyr5RCcgG6mT1go8AB+z3PmSCGHLL4\/8rAybSSdb2y4jz3cCJwgMerBxU5lQ2hesT0iwPfAP5bVRdKZPoFdTmdrwS8jlaxRi++4zWquqSFxaVH\/Oz5sA2Bi4B3RZb5jAk0IJxGG8BM4CjgRFP8TBX6dGMd2ATYKzIuUmWfEHLCn45CgWUUUuS57NgDV\/z3vbamjHgbVm1zFvDqyHvplTIaMmV7YHwgA7lYRDHtAfzASngZKKVKBuA6wEspW13XrpDWsWhKT8J2JjybqvoG4Fxg7UiATlZIfCiizw8APzCalX6nT3s+VdVZwFfM8EuVybFn+nURuTEusKgVfOjZhCReifuq3eNB4LoJCFU0VXUR84zWoVxl0WirGSmj3bx3YdDrVFQxDQMfAr5jSn6gkLpiBRXgzfSuolJMIC8EvLbHxuXWwKnAy3rMzzn0+VXj+1q\/85U95+6E\/F\/uM9eAq4FvWqiuSSnrRFU9rrgDIZZfyoMAOA94sFf5o6ikcnFCmevWxjC96rvxEOA1wHtF5EmzDgaeUdnl\/TP7q+qHzOCoDbalo8TxcPH2tFoQeiWUAbZ05VFYGTWjsPvsHvNzLn0eqqofMQU61I90EXlHyxDCjSV6S4eBQ7wfKpZ\/tTK0LEorXFdScVwiIsO9JCiL5f7ELMNeh+nqhP6Ed4nIo6UZcrBGJf4vqOpyLrAGWzKm0EFV1ydUhaWGY7q1jjHjb9H4+wu9S934edUe83Mp+jxGVdc3pVTrQ7qomXw\/mpBfzPGO3CD\/oYhc6KHV0Ygj54EbUWUOhTRoHXiC0ABZ4p5jWVNKCDPuwsSE6e4A3ikitw8giXq+PBSwCrDvFAmNTOZeAbxxArwJVz4rEZARinpHhCT5NvRPmK7TnjfMi\/t385D6LbTs4c+tgD0zlZHLwDuBr3lV3ViEmPPASogHr1boni6kbwPmtMcYC4Yo\/J4XAX+lDNTRWJ5RjQAv8h4RuXk0y2Cwerp2U9XZVgI8UEpjK4nNaaFi9NozgEI556iIYX1CX1rpggxtu0otr0j+N2CTPvSSmlYY9A1gVqbn7HnJo0XkLlp5qbIKyX5uRsACGy5ACP75qyzhX+tVjsWsqmeAL\/TIE\/PS2UeA3UXkiomEP+qz0ERzFMYe6yrN8OsSylVhUOAwGg+MqOqyhOrSiaIHCGHy3OcXE5xDhLDSorSKokoYk8MR3fg1TAtWqISsWxg4pM1Qnmy68Nz2Pibfc\/bUvaPficiJlrtvdFIoSYRgfQR1YKuCzO6u3JlObL3dd60BfyJ0cNcKWodOrCPA+0XkjwuoMnK6qLUxdacrVmClvn+bNg98sF4oA9YnQH6VEubdrFVUdWXH\/0sPdogCWwDvIL8CLOZdR1\/w6kBHPZhh\/yYFaHQo8uI3diOhD5RRQ1VXAz6fyYvOb48DnxxPT9QzmVwJGF5bF\/K43K17AjjfCK1nFWhWYVcTkadU9RgC4u8s8stem9H+HCQif1iAlZESwCafZvz8hNr+L88L0RhyzuJ5L36qgp5O0FqfUI49TDUAT00wRt3oXNp47i5a5dBVedgF3mGJzzLWuzQJgLnnArcDz\/DCvOT2wNvNuykhL2rAhwl5856kKSp4nK4UjyDgPDZIyy1qFCX6hojcMJ4cLFGBsh4BFr2UZSLAxSLyxISY7lZyKSLnqur5wE6UiUELcKCIHG\/hhAXNMteIsT9OyNXNoIVf1UlYLQfsC3yUclVS66UKvWl7QC24oJmRB1lLoPOU5Uj+mwA\/TzE825Cw30QZdJgaoTn+cOCmsUY1qOqPCGCn3wR2jmRGarMowDaq+lLgiUk0niTq4\/pQhjIiUkbXAl\/3EvJurMcca+LNBb0YF9pnGUBmiT4p6QJs05\/\/SAIAYY6F5Yr5yyJyrJd2L+CW+cMi8rCI3CciD41zPSAic0Tk48B7zDLN2Ts\/y8XJRzqermsJ81SqyATn1RuASzI8141V9SWmGCXxHrubp5JqSMZ8+0VgJxG5VkTmq2p9lGuGiDRF5Bbzko7N9GrcY1wT2MxkxWT1JalVTX+LVlgyl\/cOEZHnGKOQoYhCigTsWyjTSOeHMAJcVqLD3ku7o6a\/Md1++79\/J\/QwpFQaxUT9XQJYaq+H+k2VNcOMghmxgTDOVReR081SLZFL9FEaAyihFwuMDS18VkWg+3lcQJh\/liqEN6PV+1SrwNtezLAkrR5IzZA9NeB7IvI5oKaqNfcgR7mGjUZdaRwGnE9rfEfKOTiCxaaT6DHXTU4eSqiczimdd7y6\/xKR87ptc6klPnjNfm5CudlHzgxXEfp1cggs7treSFV\/EgvDsYjC\/u1YQgKuqsXjru3xInKwKbqRQc4iHIfnA2MDodNFq3LqZKOJ3IITIYBbDtaLIwPbJfCaRh7SHxPPo0HIGa6dwO9eBbYBAe4rtRjDDd9rgE96WMk8oE5GrFouRMz6P4jWiPMc4+A10bDTCTOcokkH6wIHk5e2cEX2T+CLVSJdqZvnn9uBEAcugX3lwv8vhmJQTy2BjGYarQ78ggBm+IFOXpcR15CIzAF+WPF9HIXht8Dh3cRKB2tcD7xpzP4kIbkM5cpsB+uF640V98ab15UwHuZx4O6EM3I+2SE686oKcWNTajkTBrw\/5tluwkpjRFeuJyD3w\/h50k4ydW1gyUnykMQiEktTpibgS9Zz1DUIQC3xoZ0YtogEcq6l5hDtl+UIj7ZhgT8mxGWbpiiWoAUiOapStH\/7DqF3qBvF4tBGv8Hw6Rggd5def4+Ufuq+NoCHBlvZ4mMrCFgDeGVFnnPD7lFgrv1uTpth2a38EeBNVbDcvI\/Fch07ZMiLOCpzVobR43L01OjvmnCPJrAGARB2wgyoCMLsbYR8XA7kkvcc\/RE4yeVxLz0kiWrU18v0tNoJ\/H7g0lQrI0LuXpIwEneLSFmu1YWX1LSf9wBf7kIheU\/CFcCeIvLMABKoJyGlBwjFJjlrxK34gbEQQl72c0sMUy7hXO4BbrQ\/X5boIUEo898gMni7XYvRmm6bIoNcNpwiIvMygI6d36+z\/UhRSLFhvvIEe0Wqqi8BvkbesEJ\/56cJhQyVK1pTDjFupFuRsphRN4nIXSmEEeW1ZgEnmeXkeR3f4E+p6svH8ZI8l3QiIQY6Vi7J73018O4ILHWgjPpTqd1N7yFxpuLailZ+rqogusXHpwC3JHoYLoTf3KYou1FkryT0yaSkDNwLeA64MscjMSN4SETuJeTUUqNG\/v2vyvDWKhsmJmsPI4QLc0KfrguOEZHrUyDSUhSJf8G2pFeVjHUQZ6fkX9wzso39JgEsNU4wegJ1BeCATmWVDsIpIo+YxaAdlNF1wDtE5M6BMuq5NZ9rtV1TJXQwrTV0K6z9UvMwUo3Sv0W\/u8eEe9WwaiPy1KquLcirrBNCAdU\/2mRbjsd5Y4Go0YoTRAdDBHDs9QmVdTm1AB6qmwN8OzWPXqv4Ah4SW5QWMGKJennfhN9WRWdwiHQr0\/weoQnTQ2nS9h1NYE9VXcsOYmjs22oN+B9C9U1c4eUb\/zCwj4j8M6cAY7C6toQXTRQ+fi6Xx570Ar58D1anNblVKp6LAtdHv7uTgLhQVRA9n8xX1ZUqAuCuVcBQmSsi942FPp1AZ7eRD780USE7f2afApvz3N768+koj95MJcyqAuIVhJhvCdwrJ4LrCRAdlRSkvXiDgJN0AGOHEJ3glgf2i0qLZQwvSax66FttXlaNkOt6l4hcVjVpN1hJy4XmSIIA8pDrn3PCMtPNSbKfG5sgSgm7z6eVN8J44t4ET8MV2Iq0wF1rXT7\/Rhl74HRwXVvoKle4300LZDr1fi+dCKPE3ndXAjpNLniqAD8Wkd\/nDFRNrbLbviBjO2ruOSLyXEXIDIedPwj4Eq0BUNLBrVZgb1V9ZUdqbQE+\/pQAeyP2+ecIBQx\/8o7tgXzrTVjJDIalaFVS1RJoq2bK6IYJAOudGm5ni7ZTwmTOm3NE5H47qxkGsXNn2\/\/pVjE4jNBm3XzeqgNnEiCmUo0M\/8zchGfutC\/\/JKCL5KyJ6JcbseKvL5GHsu\/l4XOBI4xvk3VDLYGY1TRqiUOMXb2LI6XRlcAy935vAjJCjRC\/li4IZ1HgK12gQbhy\/Bot2Pl9ReRsS9gNcNF6o4x8UmUT2M0s5ybpAI+\/EpGnCljB02VvMR5ImUfk+3dVdC\/\/3WW0ihRS5NCmqjqrE\/p39PuVac3oSZV9SoEm\/LY1TLVRK+1jV5TQ6NvralABPkMIh6f2HDk6TRP4ooj8iwo9R6OtekVCVlVdngArUSL84UJmbuQ6N7t4Fu9k3tmUURVgQ3eld1LV11nYbSwEWs8l\/ZHQYHu5iJy8ACN3J9OZWbRDHfIDbhw0bG9HDI7\/P0mvohoCbgJO9unGg6N4nv7XppWrkIr7WjMPSdsGaP6NUJ6\/SMUzi+eqLQP8q0PIy\/O5K5KOTRgD\/z5XWCFJZBhLwmeTHIUE5b8h8DHyGmDd+LiQ0HM0lMtjVSwZh5bYmnIxTt+MK4Bbu0ksRhAXbyP0GlUl\/hiy5Ci7T2O0UGFUYNFU1d0jZPCBYKu2HhwLNXmMM16cEBY+ntAkmKKQ\/Ow+IyJPDqogX2Rcvom0cQ3+f6+OogiN6HePJSgKVw5LmLH7ry4+syTVxmSMtp4lFCFkKyRTzkIIW86lNRyyirB3edjLSQfOA18lDFXNgQgSU+iHicizJRDKU7pxt7LPjZA\/GsAP6wo70HqnMFg0OOrVwM+M8FM0vBPLG4HtROScTto96gyXgTJKItqPqeqtdMYHdIt4WbOUt2xj0iqKyFEdjhOR0wdGxKjCc8dIEVQBVB0iVNPdEwty4435qjqHUDiUurYFzuigIPxZV7IzzoW4aZTcVzNu9zDZlHLvminKnkQqgEdU9X2EvGzO3nnry9dF5KpSBl9XCsXDHda3UCpc51Ud8whIuR2JI1JGGxnBLp65oT7F9EhVPa+DoHw+ljvo8E8OP+yTaMlJwvl6gvw84D8GuIIvMqya1hy+ekZE42rg7jH29nIC+nZVr9b\/71uAg7vgtaHCdFpS4f+1T0ngaQKgwWfJL3F3OvhmSRDYbpndk8GrAetSdszxXODyTqWCjrWkqqsAvySUnedaRh4e3ArY3azGIQarF2uEUCbczTUchTqqAn42I2X0bhF5xgTEIFT3QiH+OtJDoRAQVRpAPVIcfp9LMoX8ioY4PRaMkP9uqdhD6zPFP5R79erRgEMI\/VtV5P9Ya2mLaBRbtQov4oS8GHnwEvE9FbjI+346KKOmqi5DaFRdg3JwRf4Mh1oJpA5m5fQsVDCzy2tGReu32eZN\/QDYVUQe8XlYg+1\/0drS9roKHzu6idICUh1NRtwMPElaQl8Jg\/a27+AF+X1fHp1\/f4UGwkDOrKtH0YrZtLD\/cuSch95XAD5Uksdq3W6wFRyk9oN02qjTOlgaroxmE8Ycb07eSN2xNvbVwAcdNmggr6bUqtl1NwFt\/WMi8nhOc950XNG48oVoNaCm8OujkUIaTXA+REBnT6lqdAW5ZZf\/d7DSjHApxHcAe6nqbJPTUuqmHQnZ\/rg4rb6FUi\/0hBHvWN+rNnX1JMIQsWHKj\/b18syPm5fUnEwvqcJE1a6vac5cfwY+DWwoIr\/wdx54RmNaySsTSn6rjsn2\/bwfuHm0\/JHt+9OkjaKIn3FtVV16HBihQSQjjw5K3EcJzckHlrp3V96AEd8WhLLMEl\/s6AwXAA+2EXysBAU4AdiZFj5dLyzsJqFBbP8So9Mz3X0tfU1zS+8W4Hci8rDv38DL7SiIXk2I\/aeG3W+0QXYvCIfan71Iak6inPC87qsIyXcGZ9nXyw2O95VKeXRz2E54b2lXHJkvIsDFZgU9nxyNuvTVlNFHCEnxoR4zqwL\/rqrLMom5JFWdqaqz7GeJayHzMqergP0wcKWqXqGqu6rqoh5iHuQDX8hzth9bJ4ZtJPJIx5IDLqBuJlR0VUX+jmGE1isobwarN8tbZdYgYHtW9bpftOpdeEZqcedtI6LL+VI1gnuWMKmx\/fu8ou5IQrlwyZzReMy2BHC4iBxaAP03dZ1MaPorkf\/wvf4N8P1p7CnNJLQjnApcoqpHi8g5URhpgRdqEarCTrRwGVMMgIs7KAr\/3T8IOb21EpSfG8nbqupxA+DiKaOYDlLVX1oTejLPjWc5u3LYgBbMSK4L7QrtBmwkAK0EpaMwHA4cTVr5b45gA9hHVX8kItdNUkPlzlSf4Dneumeah6JiHLAtgTNtFMlnrYN8gUZpiATEmoTWjRTeEELBwm0dlJ4PqntAVV0hVS0U8v+7PQER5uGBUdH3ysgLw95gxm9y71+ty3\/f3IijRLm3rzk28rvu6L2mjPYnwFpMpDLyd20S4DQOnMRwwZP27iP2M+fynp5505wpvDDFcc7qhIFjP1fVhUtVAE3h5XycCor8PKCq0WfHs7C9vjLRgHVh9lJsrPlgTRmj8LBc4288Ymmoatew8BU0qgLn+TgAs6rmq+pupoyUNHDCUs+2h6q+1gRZbRKeofQ12YnhZoIybWbsn3vd7wD+y2hYFmCl5O+9NS24oKrnB3CliAyP47H45ObLyAfufFvb84\/2ToPVPwbh1tgo+tTm3loHN9813dKEhlgoN4zvKcL8IyV0ezdUdVfgx4TG2xLflfOMs4CjBoRf1EJPUaKNRCPIvaVh4P3Avy+oPWYR7NdsAsJ3Dk3\/vU3pd+Lxy0lH0naDdNtRntfv9cyAP\/tqefTso220V2nVu7Cq1gFWoQyY6vOEbXFm94w2BY4ldGlPtuBwC3IHVX2rTUCsD5KrWQp+DqGhstvY8iyjuZe3Caiq5+jgm0eq6tnA1QtgPsnzspvYnlbdSy\/nfoouZgdFntN9wK20yrdTPLpVVXUdEbkhOje\/\/52TbLiOZwTkKMqp2K7hcnN7Vd1aRC5OGUdR70BYfqMdCx68FzScEeHTbUAYI7EsE1NR183GNgiVW4eq6gXAc4PEapIiciLdR0SuqMjU61jI5lOEqsNUpdQ0Q+cTIrKn6gJ7hBuaoq9qWDrP\/oMwIsYrb7s5i8tNIVWtzI3zSJsSCqDakeJLNniWFSCtsTVTbVWZKzdaFGSEkIPfS1UvISHs3g1hvrngwbmAuMTyM2sB\/0sLLLVfwE3rppReD7xRRH5bYvjUAryWtF4oH1syLmOIyA2EseMXE4YjrkT6qBGA96rqt0RkzoJiXERwQXVaKP2pRuStBsk0buVpBPl1KbB34vd6P9KWBKSW9vN6iBbIc2ozu3ZJj1X2W1V1S3vu4URv9DYROX0SDMhcp8P1yXsIo9Fvq8pr9XE2dm0CgkGJ5d7PdQTokZcBJ5oyKhkOLLW8wu9LqnourXj4YCWcvQlGug19mgFQF5FLVfUQ86KHSJ8eOwv4APBJu8+CEIKN4V22aVPQVWWEoy\/UdXw300uBrzWhXEvkP4ANVHVJEXm0Da7okUhp5QjQJdv2qsTaGTg84\/PnA6dPYBGO89TtxicrZCr5hQlD+\/ar+g71DsTQIEyVnEkZQD63tM4zIj0X2IRWmW6\/MvP6hFEGPx5MHZ3AzQ9WeMMU0xmEMclvJG3CpQuaLaPKzgUpGb4mYTR4iofp+\/QBVd3KBNZ4gltU1cM3qd377vmsZ0bro9HvIPTWzUtUSP5OCwGrEioCS9LDfFrjUFImxs6fQNrw77yfkJ7ZkzAvKVXZu67YTVW\/KCJzq3hJ9Q4EJSYAKKA0nCjnEyp1fhApo36eQeSb+DlLij84yCVN\/BlY+Oc0o0fJEECvANYQkVtM0U1348JzPa8vYP2va9dEGoQjZm1vShgGF+dm7iWgvSye+T0L9eDZ16WVi6k6pHAi211ceQwDe4vIrar6G+AA0gegujOzFKHi7qgqEYnaKBRcs7DKihEBlkL3fgzY10In\/a6MYi9pdWCPCQLu1B5dU1ao2s8\/ZdCif2YZs4hhASgXjsB1dy4U4RipeDUK8d\/WPk7EUgkiIvfSatLVxPeB1rC6kvSwcIG9ZoLkjAD7isiZqjrLpt1eQF4I05XqHqq6\/Dio7Z0VUqQkXkN6IrmTQNg8w42vstGlFJLf80BVXc6szl4qpVm0+mgk8xqynzOY+uuBzHN0tPiVOtD+dHKNxH6uVkjo1ixKUuXK5XHngR2NL9pLqm8vIPRX7oFCWiXznrdPBInY\/n5eRE60iIF7MT8lr8jBvaRVaKGDdLUX9Q4Htan9+3Bhgdbr8Q6l7+3lpisBB4vIp3qcf\/gUIfZeElz1qmkgY3PzjO6RL8GCsVwobBdZ7FPNK\/TnXRrYmDAePV5X0Roamnrv1Qxeal5OOD4qBJttz5uzHu\/xvnoR2U9E5GgzsJvRu59BKD5bL0Nee77vYFU9pVvQ1foom9pQ1UVpVeXUekRkpZd7co\/bhs8u+H2+ufup6gkicmevckkicgKDNZZy7af7TBVhvlnkIQ5N4XPf0RRSXNhwTYH9WYUAOHs9+WEqJaBhLJL5znf3cD+9HuACwlDSmskdH\/\/jJfsnEMAKUukmBlbYBfhZN\/tbG+MmLycUHegUIWLX4s8C7wU+Q\/nkoBISfUf1MuRjc3xKX9MhXzKAiKlgrRMqFJcghN6n8vKqym1HMSiuLuBBLmtCM5en\/bOvNYWUUw16R49o3uX5ncAHReRJrGholP\/7v8C\/eHFDctWzU2D\/Fml2lkVjHcB2dFfe2S\/KyBXSniJyNmGm0M2UT+g3gV1U9TXmSRYvV7fEbelrKnsF8aTTwepSONqZr0XoI5zUKciFzn81VV3FhKf\/7j7CxODU2WWx9+XeQ4YdoBJFlpqJ7zoC\/LOHiv1hYFcRuceanLVd\/tjv7wF+SRoY74u8dFX9t24G+NXGOKCdpggRu8KpEWbf\/MJw554DjqRss5sT\/ZIESKEZDKZZTqRA2jGD0RfUPVuXkI9sMHWLOJzvlicURMVy63Hg0gxl4o3Wu6jqSh6hSNBE3kKwJumpDk853EpAoYDyYeph4NMicpXJyfH27FQChmE9Q8F6yO9DqjpzvHOqxW6+JeUcP2oqWFR+iEeKyJedMMxSOZ1QKuwYSyWWE977gNf6qOyB\/OtZ6KlmlmedULpcimam855JVGa77TR5rRHjY5+P1DSB2qQ1wTZVcSuhCOEgs+CT5J599sPAyxINAKfLfxCagHuh2OcT4Lg6Guom14aAK4CLMhWjK7MdMPiqTjKzNopVtTWhqWkqKKMh4FgR+U8HazUiHbJeqq8TIH9Kekq+b0eaoBx4SV3wq5frqmq3Vy3whjQJuFhrkhaXdwvRK0XvL2x9voAu7LlrPcoFVskJLhYppKGpTj9R6GeRNsv+UkJLQK4Vv5+qblE1FO\/Yfjax4CDSy6WdHv\/m+IM9CLULsHCX91Xb5x9SJh8\/izAGpmMapdamySDkj2aYVdKPXpJGFtPJhPDZUPySbiGKyJnAOZFrXkoZNYG3AO8wr3KqM3yv17A1afrPbq6mMfpngP8gD4nYLd+naFUwlWb2hr1f0w2jHl7ahfBelYBMkRN675fmbOff1xEa9t1LGgJuotXWkDo7C2BR4KequrrJD1HVuqoOjWYs+b8Zja5L6N1ZpO2eVfbZW2yu6TEvdqW0o0KH3xHQ1nOMetczb1PVV3lz81julFflDFu592Z9Lty8bPF\/gL18k0ZhUv\/71whjDKTwodaATxjUxvAA567jWkpVl4oMnfE8mcUJ4xL2IuSOSiFk3GMhkZKhO6erFW3IZIPetjbMAG4Ukes6he0IKP1a6N36wUNqEGB+NiQULMXG5+\/sfVNpZChS4n9S1Y8Cv+8ABOw4dajqNsAJkQef6h3VCNV1Vzje4qRb\/obao6rfB44jbyKDN6Z\/0vjaqxxfrJAIVTkNVX0loQRyIiBycpTRnwjzbZpjKQLTwjURuURVTyLEd0v1YnguaSvgPSLyk0EuaUxhViP0Mzzdxd43CTNwSoeMXTDPFZGHPDdV0GPGDLlTJ2hvv0toOOxE+2+iVSGVqlhGCHmHEpOihwhAzTn0pMBbCdVfcbnyz4DPEfI3OR5hg1A8cSbwM1U93byDuYTQv0dHXk4AXd6JAIVGIdnyFxG5vw8Hgp5le7B8htL1M9lFVdcTketGG2VSb\/vPGxE62ftxHIQ\/04XAuwyOfjyvxN\/rO8A7SQcMHIs5FPisqv6KwRC\/Tnu1XGJYoRTYpJ\/3BZEBNtKD\/qzmBPHA\/LE8IzPSlid02ed4OWpC\/rzIAEs13kYIJejH0UIATxm2KMB2qjpTROZH7\/yoqp4CHJipgOPQ\/u523UMoLx+O+H4ZQjNtu8LNoU8ljOOZCDrqbsMDLdUJZeinE0BXc8J2Drr6bgIShI7qIUVVOa+nP8u93TO6EXh\/l8oorha5FviJEWypIXtORGsB+4nItwtb3tNpaZd05f+nF+gg8yKG79WgxV57yTVa+G6dhP\/rSIdI8jN4BjjJQExLhH+uBQ4xozcn9LMcAUbo0igqocD3CcMAF8o0OiWiESHMBlphjH1yuZQjL\/1ZL8IqBvss9K\/mcf802t9cOKG9VPX\/i8jd7UZ8XLGzCC14\/34KP7krfCuwm4jca65eswKDAXyDUN+f03k8lqA9VFWXofvRzguil9QNWGytB8aQn\/UvR2OAabo2J78w6Z\/Oa5lX3fpPnjXDENKLDzzHuHXk6XrY\/mZCaLhURa0DEzdNBsVXsy3ClCtDmsDXPc3QV4xrrS0icjktLMFceKUVCIg6L\/LgYwGwKSE22k8ekiujOwgVbdd7eXcVtzP8kLuAH1EWUsiV24oECPepArW0IHlmmLX\/3cwQVn+\/aAsuaBHSx5XHe+YNp141mHqNuJUN\/K3NUk6RB0QKqd0APAa4q6DR6UbSUNtVynBy+XYBcO54\/UGTS14qhNRHLg\/5Z\/c1Wn3BGcYbu1OfbYYL96cJBQzXR81wqRv6FSNYKFtlpcD+qrqmCYVBgUN\/LG8POFZE\/l7Rs55yXqgJ\/ZVp5Y9S6ND35\/yCCtwVyRwzDnLDaWur6opmmErkJT0IHDpFjA43\/OcRRkAM04J86kfiUlOc1xaQnwqsAezTbsTHlsQbKN9AmhtmeRx4n4j81oTJSMZmiog8Bnyb8pBCDUJse+9BUUNfKaMZhPHUxzjE\/jR+XxfC65OOFhDT87WlFJIpDCF0\/j+aEfbxM1yZFrZhLfqOmoicBhxPWYSWXsm4GvAlqwSuFPmZaGVkz\/d0FGXKCds5H35AVRcj9JTVcI2squuRP1SqtOUgwAGmjGaUOCxjih8RxqiPWgefuByx4QBV3TBiwMGanOXJ5jsJk34fisJG09U9ahjNbZshLFyJ3UR5RAsxgXZ1ptL1fpZNRnk+j4QcTGiI92bTfjSWhghtAl+dIj2MjrbyG0IJeI6BN2TnuCGwQwyY6xbUVgTQ0MnelLga61AR+amF6YYLcEPTFPAThIqcXoynWISAKtAPin1BXF75NEQo132niNw8GqrxNF1DBHDPVNp2\/r9SRB4ondOw+51fICIBAUZoZqSI40jIfOAjwJWmvBp9Rp91Qo7uwKnitZtDMCQitxP6knJpQ2wfDnPvUFXFq+y2iiwkmcTD8obcw7yMumSDWES8PzdiLRnGcVf07aq6ucO4D3TEhNGOV5QNAX8FdhSRq0drvpt2L9\/yxtcgIHzHgrsqDUPoEQEoiqdm98rNTXlBxJa0GqglNjxNbtwNvB34M60+qskU\/j4baMiU0a4icp8ZyVMllOzP+QNCo3AOJJuf4xaR\/pEaobLutZGFNZlhlhrwPRH5Vg+BS0VE5gFHUHZekiukRYHPeM5iELqbELrBrK15hObLN6VUZE7h5eGUHcibDVQ3QXNd9LuSRgMELMEHMixs\/9zijAFzFimluQTMyRNp9XBNRl5pJPr+\/zb6vHeq0aenIkTkCkLPVK789M+7vJQaYeTuWuR1OJcQKnXgOBE5yB6u0aMwi9f6XwScTSueWSpk0iRg570+B85+sF5AsH41I0sz3nMBfgvsIiIfF5HHFzBsQa+wy5kZ5Xt6H608Ty\/27wlCoUnu\/dX4jHGU0lMishewH3A7rd4hHYWWStJtfO+6KeIDRGRvEXlqCld8ujw7nvy0h392G2AbEWnUzfWdT6t7WifwxVzQzCLgUR3oaAe9ivlHFSPPquoxhJ6GUujmMXbYF4Dzp4FQHDb6mCjl6nRRizx2GSPM8yRwGnCKiPzBrA2nnyr73rB3bNDfMX1\/vkZkXbknvjgBzmaYVgNn1XBMjdAWcV\/pUKej4ovIfFW9lIBJN994TxOfdZNOnlxcXCQiJ6jq2QS0gQMImIkSeTBxc3aO4eQAuH7v+ea1H2\/5TH+eRsJ3pObSnXeHC8h3\/\/w5wPWEicSNRN3hE3JnEOCELqwDHyMP9LDEOosAv+NWTU+VokMKiciFqnoB5Ya\/xWsrVT1QRL43hfMYNQKg4mTThxJGRzxm4Z7LCbmISywO73mU1BDIkn3wjlXWErGHKCLDqrq9RTugNfspZV1jyqOX1vV15jXkIh282vK1l47FYy5LrDjqTuAIVT2BMLtoZwJKd71N2XU76kQjPqlFHnvDvLHfW9Tn5ugZUkOGMwnpgJw104z\/bMOC0B\/6K+CoTHrzz+6nqj+vm2cymfX6zwH\/T0SenOAwi3\/PEabpS1YUuUXyeCcLbgqsp4CjScdFy\/3ue0xYPGqhpNtHw1bzScEZSv9UC6mUAN7tNc3WaE1J1YiOHySMWskNvZ\/Rw3Cdn88VwGcJQwRzPG+JZJeOI0hHIu\/5buCTqvpZAiDA5gSMvdXNy0yhgbkmR64mFC38QUSeiYwlySzQupswqDInzz8M3FJAJjm+nefmZpGfSwo83C+cNkDKHqwu6aQWGQ86oJnBSpE1tKYR++8WJjS3r0go9FrBvKfFRlHONfMQ7jBFdBvwMHCXFUy1G0oDGu1y\/R9F77us8A\/q4wAAAABJRU5ErkJggg==';\nconst $=id=>document.getElementById(id);\nfunction toast(m){const t=$('msg');t.textContent=m;t.classList.add('show');clearTimeout(t._t);t._t=setTimeout(()=>t.classList.remove('show'),2000);}\nfunction el(tag,cls,html){const e=document.createElement(tag);if(cls)e.className=cls;if(html!=null)e.innerHTML=html;return e;}\nfunction ctx2d(cv){try{return cv&&cv.getContext?cv.getContext('2d'):null;}catch(e){return null;}}\nconst rad=d=>d*Math.PI\/180;\nconst clamp=(v,a,b)=>Math.max(a,Math.min(b,v));\n\n\/* ---------- shared photo math ---------- *\/\nconst FST=[1,1.1,1.2,1.4,1.6,1.8,2,2.2,2.5,2.8,3.2,3.5,4,4.5,5,5.6,6.3,7.1,8,9,10,11,13,14,16,18,20,22,25,29,32];\nfunction fmtN(N){if(!(N>0))return '\u2014';if(N<0.95)return '< f\/1';if(N>34)return '> f\/32';let b=FST[0];FST.forEach(v=>{if(Math.abs(Math.log2(v\/N))<Math.abs(Math.log2(b\/N)))b=v;});return 'f\/'+b;}\nfunction fmtT(t){return t>=1?(t+'s'):'1\/'+Math.round(1\/t);}\nfunction fmtLux(e){return e>=10000?Math.round(e\/1000)+'k':e>=1000?(e\/1000).toFixed(1)+'k':Math.round(e)+'';}\nfunction kToRGB(k){const t=k\/100;let r,g,b;if(t<=66){r=255;g=99.4708025861*Math.log(t)-161.1195681661;b=t<=19?0:138.5177312231*Math.log(t-10)-305.0447927307;}else{r=329.698727446*Math.pow(t-60,-0.1332047592);g=288.1221695283*Math.pow(t-60,-0.0755148492);b=255;}const c=x=>clamp(x,0,255)\/255;return [c(r),c(g),c(b)];}\nfunction wbColor(k,wb){const a=kToRGB(k),w=kToRGB(wb);const r=[a[0]\/Math.max(.01,w[0]),a[1]\/Math.max(.01,w[1]),a[2]\/Math.max(.01,w[2])];const m=Math.max(r[0],r[1],r[2]);return r.map(x=>x\/m);}\nfunction rgbCss(c,mul){mul=mul||1;return 'rgb('+c.map(x=>Math.round(clamp(x*mul,0,1)*255)).join(',')+')';}\n\n\/* ---------- TABS ---------- *\/\nlet TAB='learn';\nfunction setTab(t){TAB=t;document.querySelectorAll('.tab').forEach(b=>b.classList.toggle('on',b.dataset.t===t));$('pLearn').classList.toggle('on',t==='learn');$('pStudio').classList.toggle('on',t==='studio');$('studioActs').style.display=t==='studio'?'flex':'none';if(t==='studio')initStudio();}\ndocument.querySelectorAll('.tab').forEach(b=>b.onclick=()=>setTab(b.dataset.t));\n\n\/* =====================================================================\n   TAB 1 \u2014 H\u1eccC NHI\u1ebeP \u1ea2NH\n   ===================================================================== *\/\nconst APS=[1.4,2,2.8,4,5.6,8,11,16,22];\nconst SHS=[1\/4000,1\/2000,1\/1000,1\/500,1\/250,1\/125,1\/60,1\/30,1\/15,1\/8,1\/4,1\/2,1];\nconst ISS=[100,200,400,800,1600,3200,6400,12800];\nfunction sld(label,min,max,step,val,fmt,on,noType){const w=el('div','ctl');const h=el('div','ctlh');const lb=el('span',null,label);const vb=el('b',null,fmt(val));h.append(lb,vb);const r=document.createElement('input');r.type='range';r.min=min;r.max=max;r.step=step;r.value=val;r.setAttribute('aria-label',label);r.oninput=()=>{const v=+r.value;vb.textContent=fmt(v);on(v);};\n if(!noType){vb.classList.add('typ');vb.title='B\u1ea5m \u0111\u1ec3 nh\u1eadp s\u1ed1 ch\u00ednh x\u00e1c';vb.onclick=()=>{const s=prompt(label+' ('+min+' \u2013 '+max+')',r.value);if(s==null)return;const v=parseFloat(String(s).replace(',','.'));if(isNaN(v))return;r.value=clamp(v,+min,+max);r.oninput();};}\n w.append(h,r);w._r=r;w._v=vb;return w;}\nfunction selc(label,opts,val,on){const w=el('div','ctl');w.appendChild(el('div','ctlh','<span>'+label+'<\/span>'));const s=document.createElement('select');s.setAttribute('aria-label',label);opts.forEach(o=>{const op=document.createElement('option');op.value=o[0];op.textContent=o[1];if(String(o[0])===String(val))op.selected=true;s.appendChild(op);});s.onchange=()=>on(s.value);w.appendChild(s);return w;}\nfunction segc(opts,val,on){const w=el('div','seg');opts.forEach(o=>{const b=el('button',String(o[0])===String(val)?'on':'',o[1]);b.onclick=()=>{[...w.children].forEach(c=>c.classList.remove('on'));b.classList.add('on');on(o[0]);};w.appendChild(b);});return w;}\n\nconst LESSONS=[\n{id:'expo',ic:'\u25d0',t:'Tam gi\u00e1c ph\u01a1i s\u00e1ng',html:`\n<h1>Tam gi\u00e1c ph\u01a1i s\u00e1ng<\/h1>\n<p class=\"lead\">M\u1ed9t b\u1ee9c \u1ea3nh s\u00e1ng hay t\u1ed1i ph\u1ee5 thu\u1ed9c v\u00e0o ba th\u1ee9: kh\u1ea9u \u0111\u1ed9, t\u1ed1c \u0111\u1ed9 m\u00e0n tr\u1eadp v\u00e0 ISO. \u0110\u1ed5i m\u1ed9t th\u1ee9 th\u00ec ph\u1ea3i b\u00f9 b\u1eb1ng th\u1ee9 kh\u00e1c \u2014 v\u00e0 m\u1ed7i th\u1ee9 \u0111\u1ec3 l\u1ea1i d\u1ea5u v\u1ebft ri\u00eang tr\u00ean \u1ea3nh.<\/p>\n<div class=\"sim\"><canvas id=\"expoCv\" width=\"960\" height=\"540\"><\/canvas><canvas id=\"expoHist\" width=\"960\" height=\"110\" class=\"histc\"><\/canvas>\n<div class=\"simrow\" id=\"expoCtl\"><\/div><div class=\"read\" id=\"expoRead\"><\/div><div class=\"verdict\" id=\"expoVer\"><\/div><\/div>\n<h2>M\u1ed7i n\u00fat v\u1eb7n l\u00e0m g\u00ec<\/h2>\n<table class=\"tbl\"><tr><th>Th\u00f4ng s\u1ed1<\/th><th>M\u1edf r\u1ed9ng th\u00ec<\/th><th>T\u00e1c d\u1ee5ng ph\u1ee5<\/th><\/tr>\n<tr><td><b>Kh\u1ea9u \u0111\u1ed9<\/b> (f\/1.4 \u2192 f\/22)<\/td><td>S\u1ed1 f c\u00e0ng nh\u1ecf, l\u1ed7 c\u00e0ng to, \u1ea3nh c\u00e0ng s\u00e1ng<\/td><td>Ph\u00f4ng n\u1ec1n m\u1edd h\u01a1n \u2014 \u0111\u1ed9 s\u00e2u tr\u01b0\u1eddng \u1ea3nh m\u1ecfng<\/td><\/tr>\n<tr><td><b>T\u1ed1c \u0111\u1ed9<\/b> (1\/4000 \u2192 1s)<\/td><td>M\u1edf l\u00e2u h\u01a1n, \u1ea3nh s\u00e1ng h\u01a1n<\/td><td>V\u1eadt chuy\u1ec3n \u0111\u1ed9ng b\u1ecb nh\u00f2e, d\u1ec5 rung tay<\/td><\/tr>\n<tr><td><b>ISO<\/b> (100 \u2192 12800)<\/td><td>C\u1ea3m bi\u1ebfn khu\u1ebfch \u0111\u1ea1i, \u1ea3nh s\u00e1ng h\u01a1n<\/td><td>Nhi\u1ec5u h\u1ea1t t\u0103ng, m\u00e0u k\u00e9m trong<\/td><\/tr><\/table>\n<div class=\"tip\">Ch\u1ee5p kh\u1ea9u l\u1edbn ngo\u00e0i n\u1eafng g\u1eaft: f\/1.4 \u1edf ISO 100 c\u1ea7n t\u1ed1c t\u1edbi 1\/32000 gi\u00e2y, v\u01b0\u1ee3t t\u1ed1c t\u1ed1i \u0111a 1\/4000 c\u1ee7a h\u1ea7u h\u1ebft m\u00e1y. Mu\u1ed1n gi\u1eef xo\u00e1 ph\u00f4ng th\u00ec g\u1eafn <b>k\u00ednh l\u1ecdc ND<\/b> \u2014 ND4 gi\u1ea3m 2 stop, ND8 gi\u1ea3m 3 stop. Th\u1eed ngay trong \u00f4 K\u00ednh l\u1ecdc ND \u1edf tr\u00ean.<\/div>\n<div class=\"tip\">M\u1ed7i b\u01b0\u1edbc g\u1ea5p \u0111\u00f4i \/ chia \u0111\u00f4i l\u01b0\u1ee3ng s\u00e1ng g\u1ecdi l\u00e0 <b>1 stop<\/b>. f\/4 \u2192 f\/5.6 l\u00e0 t\u1ed1i \u0111i 1 stop; 1\/125 \u2192 1\/60 l\u00e0 s\u00e1ng th\u00eam 1 stop; ISO 100 \u2192 200 c\u0169ng s\u00e1ng th\u00eam 1 stop.<\/div>`,init:initExpo},\n{id:'aperture',ic:'\u25c9',t:'Kh\u1ea9u \u0111\u1ed9 & xo\u00e1 ph\u00f4ng',html:`\n<h1>Kh\u1ea9u \u0111\u1ed9 v\u00e0 \u0111\u1ed9 s\u00e2u tr\u01b0\u1eddng \u1ea3nh<\/h1>\n<p class=\"lead\">Kh\u1ea9u \u0111\u1ed9 kh\u00f4ng ch\u1ec9 \u0111\u1ec3 l\u1ea5y s\u00e1ng. N\u00f3 quy\u1ebft \u0111\u1ecbnh bao nhi\u00eau ph\u1ea7n c\u1ee7a khung h\u00ecnh n\u1eb1m trong v\u00f9ng n\u00e9t.<\/p>\n<table class=\"tbl\"><tr><th>Kh\u1ea9u<\/th><th>Hi\u1ec7u \u1ee9ng<\/th><th>D\u00f9ng khi<\/th><\/tr>\n<tr><td>f\/1.4 \u2013 f\/2.8<\/td><td>V\u00f9ng n\u00e9t m\u1ecfng, h\u1eadu c\u1ea3nh tan<\/td><td>Ch\u00e2n dung \u0111\u01a1n, t\u00e1ch ch\u1ee7 th\u1ec3 kh\u1ecfi n\u1ec1n r\u1ed1i<\/td><\/tr>\n<tr><td>f\/4 \u2013 f\/5.6<\/td><td>N\u00e9t tr\u1ecdn khu\u00f4n m\u1eb7t, n\u1ec1n v\u1eabn m\u1ec1m<\/td><td>Ch\u00e2n dung studio, profile doanh nghi\u1ec7p<\/td><\/tr>\n<tr><td>f\/8 \u2013 f\/11<\/td><td>N\u00e9t s\u00e2u, chi ti\u1ebft s\u1eafc<\/td><td>\u1ea2nh nh\u00f3m, s\u1ea3n ph\u1ea9m, ki\u1ebfn tr\u00fac<\/td><\/tr>\n<tr><td>f\/16 \u2013 f\/22<\/td><td>N\u00e9t g\u1ea7n nh\u01b0 to\u00e0n c\u1ea3nh<\/td><td>Phong c\u1ea3nh \u2014 nh\u01b0ng \u1ea3nh b\u1eaft \u0111\u1ea7u m\u1ec1m do nhi\u1ec5u x\u1ea1<\/td><\/tr><\/table>\n<h2 class=\"figh\">So s\u00e1nh<\/h2><div class=\"figrow\"><figure class=\"fig\" data-slot=\"ap_shallow\"><\/figure><figure class=\"fig\" data-slot=\"ap_deep\"><\/figure><\/div><h2>Ba th\u1ee9 l\u00e0m ph\u00f4ng m\u1edd h\u01a1n<\/h2>\n<ul><li>M\u1edf kh\u1ea9u l\u1edbn (s\u1ed1 f nh\u1ecf).<\/li><li>\u0110\u1ee9ng g\u1ea7n ch\u1ee7 th\u1ec3 h\u01a1n.<\/li><li>\u0110\u1ea9y ch\u1ee7 th\u1ec3 ra xa ph\u00f4ng n\u1ec1n \u2014 trong studio, \u0111\u00e2y l\u00e0 c\u00e1ch r\u1ebb nh\u1ea5t.<\/li><\/ul>\n<div class=\"tip\">Ch\u1ee5p profile doanh nghi\u1ec7p v\u1edbi \u0111\u00e8n studio, f\/5.6 \u2013 f\/8 l\u00e0 v\u00f9ng an to\u00e0n: m\u1eaft, m\u0169i, tai \u0111\u1ec1u n\u00e9t, kh\u00f4ng lo l\u1ec7ch n\u00e9t khi kh\u00e1ch nh\u00fac nh\u00edch.<\/div>`},\n{id:'shutter',ic:'\u25d4',t:'T\u1ed1c \u0111\u1ed9 m\u00e0n tr\u1eadp',html:`\n<h1>T\u1ed1c \u0111\u1ed9 m\u00e0n tr\u1eadp<\/h1>\n<p class=\"lead\">T\u1ed1c \u0111\u1ed9 l\u00e0 kho\u1ea3ng th\u1eddi gian c\u1ea3m bi\u1ebfn \"nh\u00ecn\" c\u1ea3nh v\u1eadt. Nhanh th\u00ec \u0111\u00f3ng b\u0103ng kho\u1ea3nh kh\u1eafc, ch\u1eadm th\u00ec k\u1ec3 c\u00e2u chuy\u1ec7n v\u1ec1 chuy\u1ec3n \u0111\u1ed9ng.<\/p>\n<table class=\"tbl\"><tr><th>T\u1ed1c \u0111\u1ed9<\/th><th>D\u00f9ng khi<\/th><\/tr>\n<tr><td>1\/1000 tr\u1edf l\u00ean<\/td><td>Th\u1ec3 thao, t\u00f3c bay, n\u01b0\u1edbc b\u1eafn<\/td><\/tr>\n<tr><td>1\/200 \u2013 1\/250<\/td><td>Gi\u1edbi h\u1ea1n \u0111\u1ed3ng b\u1ed9 \u0111\u00e8n flash c\u1ee7a h\u1ea7u h\u1ebft m\u00e1y<\/td><\/tr>\n<tr><td>1\/60 \u2013 1\/125<\/td><td>Ch\u00e2n dung c\u1ea7m tay, s\u1ef1 ki\u1ec7n trong nh\u00e0<\/td><\/tr>\n<tr><td>1\/15 tr\u1edf xu\u1ed1ng<\/td><td>C\u1ea7n ch\u00e2n m\u00e1y \u2014 v\u1ec7t \u0111\u00e8n xe, n\u01b0\u1edbc ch\u1ea3y m\u01b0\u1ee3t<\/td><\/tr><\/table>\n<h2 class=\"figh\">So s\u00e1nh<\/h2><div class=\"figrow\"><figure class=\"fig\" data-slot=\"sh_freeze\"><\/figure><figure class=\"fig\" data-slot=\"sh_blur\"><\/figure><\/div><div class=\"tip\"><b>Quy t\u1eafc c\u1ea7m tay:<\/b> t\u1ed1c \u0111\u1ed9 kh\u00f4ng ch\u1eadm h\u01a1n 1 \/ ti\u00eau c\u1ef1. \u1ed0ng 85mm th\u00ec gi\u1eef t\u1eeb 1\/100 tr\u1edf l\u00ean. M\u00e1y c\u00f3 ch\u1ed1ng rung th\u00ec n\u1edbi \u0111\u01b0\u1ee3c 2\u20133 stop.<\/div>\n<h2>T\u1ed1c \u0111\u1ed9 v\u00e0 \u0111\u00e8n flash<\/h2>\n<p>V\u1edbi flash, t\u1ed1c \u0111\u1ed9 g\u1ea7n nh\u01b0 kh\u00f4ng \u1ea3nh h\u01b0\u1edfng \u0111\u1ed9 s\u00e1ng ch\u1ee7 th\u1ec3 \u2014 tia ch\u1edbp ch\u1ec9 k\u00e9o d\u00e0i v\u00e0i ph\u1ea7n ngh\u00ecn gi\u00e2y. T\u1ed1c \u0111\u1ed9 l\u00fac n\u00e0y ch\u1ec9 quy\u1ebft \u0111\u1ecbnh bao nhi\u00eau <b>\u00e1nh s\u00e1ng m\u00f4i tr\u01b0\u1eddng<\/b> l\u1ecdt v\u00e0o. V\u01b0\u1ee3t t\u1ed1c \u0111\u1ed3ng b\u1ed9 (th\u01b0\u1eddng 1\/250) s\u1ebd b\u1ecb v\u1ec7t \u0111en tr\u00ean \u1ea3nh, tr\u1eeb khi \u0111\u00e8n h\u1ed7 tr\u1ee3 HSS.<\/p>`},\n{id:'iso',ic:'\u25c7',t:'ISO & nhi\u1ec5u',html:`\n<h1>ISO v\u00e0 nhi\u1ec5u h\u1ea1t<\/h1>\n<p class=\"lead\">ISO l\u00e0 m\u1ee9c khu\u1ebfch \u0111\u1ea1i t\u00edn hi\u1ec7u. N\u00f3 kh\u00f4ng th\u00eam \u00e1nh s\u00e1ng \u2014 n\u00f3 ch\u1ec9 \"v\u1eb7n to\" nh\u1eefng g\u00ec c\u1ea3m bi\u1ebfn nh\u1eadn \u0111\u01b0\u1ee3c, k\u00e9o theo c\u1ea3 nhi\u1ec5u.<\/p>\n<table class=\"tbl\"><tr><th>ISO<\/th><th>Ch\u1ea5t l\u01b0\u1ee3ng<\/th><th>B\u1ed1i c\u1ea3nh<\/th><\/tr>\n<tr><td>100 \u2013 400<\/td><td>S\u1ea1ch nh\u1ea5t, m\u00e0u chu\u1ea9n<\/td><td>Studio c\u00f3 \u0111\u00e8n, ngo\u00e0i tr\u1eddi ban ng\u00e0y<\/td><\/tr>\n<tr><td>800 \u2013 1600<\/td><td>Nhi\u1ec5u nh\u1eb9, v\u1eabn d\u00f9ng t\u1ed1t<\/td><td>S\u1ef1 ki\u1ec7n trong nh\u00e0, \u0111\u00e8n LED y\u1ebfu<\/td><\/tr>\n<tr><td>3200 \u2013 6400<\/td><td>Nhi\u1ec5u r\u00f5 \u1edf v\u00f9ng t\u1ed1i<\/td><td>\u0110\u00eam, ph\u00f3ng s\u1ef1 kh\u00f4ng d\u00f9ng \u0111\u00e8n<\/td><\/tr>\n<tr><td>12800+<\/td><td>Nhi\u1ec5u n\u1eb7ng, m\u1ea5t chi ti\u1ebft<\/td><td>Ch\u1ec9 khi kh\u00f4ng c\u00f2n l\u1ef1a ch\u1ecdn<\/td><\/tr><\/table>\n<h2 class=\"figh\">So s\u00e1nh<\/h2><div class=\"figrow\"><figure class=\"fig\" data-slot=\"iso_low\"><\/figure><figure class=\"fig\" data-slot=\"iso_high\"><\/figure><\/div><div class=\"tip\">\u1ea2nh thi\u1ebfu s\u00e1ng r\u1ed3i k\u00e9o s\u00e1ng trong h\u1eadu k\u1ef3 c\u00f2n nhi\u1ec5u h\u01a1n l\u00e0 t\u0103ng ISO ngay l\u00fac ch\u1ee5p. \u01afu ti\u00ean ph\u01a1i s\u00e1ng \u0111\u00fang, r\u1ed3i m\u1edbi t\u00ednh chuy\u1ec7n nhi\u1ec5u.<\/div>`},\n{id:'focal',ic:'\u25ce',t:'Ti\u00eau c\u1ef1 & g\u00f3c nh\u00ecn',html:`\n<h1>Ti\u00eau c\u1ef1 v\u00e0 g\u00f3c nh\u00ecn<\/h1>\n<p class=\"lead\">Ti\u00eau c\u1ef1 quy\u1ebft \u0111\u1ecbnh b\u1ea1n nh\u00ecn th\u1ea5y r\u1ed9ng hay h\u1eb9p \u2014 v\u00e0 gi\u00e1n ti\u1ebfp quy\u1ebft \u0111\u1ecbnh b\u1ea1n ph\u1ea3i \u0111\u1ee9ng c\u00e1ch ch\u1ee7 th\u1ec3 bao xa. Trong studio ch\u1eadt, \u0111\u00e2y l\u00e0 c\u00e2u h\u1ecfi \u0111\u1ea7u ti\u00ean.<\/p>\n<div class=\"sim\"><canvas id=\"focCv\" width=\"960\" height=\"400\"><\/canvas><div class=\"simrow two\" id=\"focCtl\"><\/div><div class=\"read\" id=\"focRead\"><\/div><\/div>\n<h2>C\u1ea7n \u0111\u1ee9ng xa bao nhi\u00eau (m\u00e1y full-frame, khung d\u1ecdc)<\/h2>\n<table class=\"tbl\" id=\"focTbl\"><\/table>\n<h2 class=\"figh\">So s\u00e1nh<\/h2><div class=\"figrow\"><figure class=\"fig\" data-slot=\"focal_wide\"><\/figure><figure class=\"fig\" data-slot=\"focal_tele\"><\/figure><\/div><div class=\"tip\">\u1ed0ng d\u00e0i \"n\u00e9n\" h\u1eadu c\u1ea3nh: ph\u00f4ng n\u1ec1n tr\u00f4ng g\u1ea7n v\u00e0 to h\u01a1n ph\u00eda sau ch\u1ee7 th\u1ec3. \u1ed0ng r\u1ed9ng \u0111\u1ee9ng g\u1ea7n m\u1eb7t s\u1ebd ph\u00f3ng to m\u0169i, b\u00f3p nh\u1ecf tai \u2014 tr\u00e1nh d\u00f9ng d\u01b0\u1edbi 35mm cho ch\u00e2n dung c\u1eadn.<\/div>`,init:initFocal},\n{id:'compo',ic:'\u25a6',t:'B\u1ed1 c\u1ee5c',html:`\n<h1>B\u1ed1 c\u1ee5c<\/h1>\n<p class=\"lead\">B\u1ed1 c\u1ee5c l\u00e0 c\u00e1ch d\u1eabn m\u1eaft ng\u01b0\u1eddi xem. Kh\u00f4ng c\u00f3 lu\u1eadt c\u1ee9ng \u2014 nh\u01b0ng c\u00f3 v\u00e0i l\u01b0\u1edbi gi\u00fap b\u1ea1n \u0111\u1eb7t ch\u1ee7 th\u1ec3 c\u00f3 ch\u1ee7 \u00fd thay v\u00ec v\u00f4 t\u00ecnh.<\/p>\n<div class=\"sim\"><p class=\"note\" style=\"margin-bottom:8px\">B\u1eadt l\u01b0\u1edbi tr\u00ean \u1ea3nh \u0111\u1ec3 xem ch\u1ee7 th\u1ec3 \u0111\u01b0\u1ee3c \u0111\u1eb7t \u1edf \u0111\u00e2u.<\/p><canvas id=\"cmpCv\" width=\"960\" height=\"540\"><\/canvas><div class=\"simrow two\" id=\"cmpCtl\"><\/div><\/div>\n<ul><li><b>M\u1ed9t ph\u1ea7n ba:<\/b> \u0111\u1eb7t m\u1eaft ho\u1eb7c ch\u1ee7 th\u1ec3 v\u00e0o giao \u0111i\u1ec3m, \u0111\u01b0\u1eddng ch\u00e2n tr\u1eddi v\u00e0o \u0111\u01b0\u1eddng ngang.<\/li><li><b>Kho\u1ea3ng th\u1edf:<\/b> ch\u1ee7 th\u1ec3 nh\u00ecn v\u1ec1 h\u01b0\u1edbng n\u00e0o, ch\u1eeba ch\u1ed7 tr\u1ed1ng h\u01b0\u1edbng \u0111\u00f3.<\/li><li><b>\u0110\u01b0\u1eddng d\u1eabn:<\/b> h\u00e0nh lang, \u0111\u01b0\u1eddng k\u1ebb, c\u00e1nh tay \u2014 k\u00e9o m\u1eaft v\u1ec1 \u0111i\u1ec3m ch\u00ednh.<\/li><li><b>C\u0103n gi\u1eefa<\/b> v\u1eabn \u0111\u00fang khi mu\u1ed1n \u0111\u1ed1i x\u1ee9ng, trang tr\u1ecdng, ho\u1eb7c \u1ea3nh th\u1ebb.<\/li><\/ul>`,init:initCompo},\n{id:'light',ic:'\u2600',t:'\u00c1nh s\u00e1ng c\u1ee9ng & m\u1ec1m',html:`\n<h1>\u00c1nh s\u00e1ng c\u1ee9ng, m\u1ec1m v\u00e0 kho\u1ea3ng c\u00e1ch<\/h1>\n<p class=\"lead\">\u0110\u1ed9 m\u1ec1m c\u1ee7a \u00e1nh s\u00e1ng kh\u00f4ng n\u1eb1m \u1edf c\u00f4ng su\u1ea5t \u0111\u00e8n, m\u00e0 \u1edf <b>k\u00edch th\u01b0\u1edbc ngu\u1ed3n s\u00e1ng so v\u1edbi ch\u1ee7 th\u1ec3<\/b>. Softbox to \u0111\u1eb7t g\u1ea7n cho b\u00f3ng m\u1ec1m; \u0111\u00e8n tr\u1ea7n \u0111\u1eb7t xa cho b\u00f3ng g\u1eaft.<\/p>\n<div class=\"sim\"><canvas id=\"ltCv\" width=\"960\" height=\"420\"><\/canvas><div class=\"simrow two\" id=\"ltCtl\"><\/div><div class=\"read\" id=\"ltRead\"><\/div><\/div>\n<h2>Lu\u1eadt b\u00ecnh ph\u01b0\u01a1ng ngh\u1ecbch \u0111\u1ea3o<\/h2>\n<p>G\u1ea5p \u0111\u00f4i kho\u1ea3ng c\u00e1ch \u0111\u00e8n \u2192 \u00e1nh s\u00e1ng ch\u1ec9 c\u00f2n <b>1\/4<\/b> (m\u1ea5t 2 stop). \u0110\u00e8n \u0111\u1eb7t g\u1ea7n th\u00ec s\u00e1ng r\u01a1i nhanh t\u1eeb m\u1eb7t ra ph\u00f4ng \u2014 ph\u00f4ng t\u1ed1i \u0111i. \u0110\u00e8n \u0111\u1eb7t xa th\u00ec s\u00e1ng \u0111\u1ec1u h\u01a1n gi\u1eefa ng\u01b0\u1eddi v\u00e0 n\u1ec1n.<\/p>\n<h2 class=\"figh\">V\u00ed d\u1ee5<\/h2><div class=\"figrow\"><figure class=\"fig\" data-slot=\"light_hard\"><\/figure><figure class=\"fig\" data-slot=\"light_soft\"><\/figure><\/div><figure class=\"fig\" data-slot=\"light_back\"><\/figure><div class=\"tip\">Mu\u1ed1n ph\u00f4ng tr\u1eafng tinh m\u00e0 m\u1eb7t kh\u00f4ng ch\u00e1y: k\u00e9o ng\u01b0\u1eddi m\u1eabu ra xa ph\u00f4ng, d\u00f9ng \u0111\u00e8n ri\u00eang cho ph\u00f4ng. Mu\u1ed1n ph\u00f4ng t\u1ed1i d\u1ea7n: \u0111\u01b0a \u0111\u00e8n ch\u00ednh s\u00e1t m\u1eb7t.<\/div>\n<div class=\"minib\" style=\"max-width:360px\"><button onclick=\"openPreset('rembrandt')\">Th\u1eed ngay trong Studio 3D<\/button><\/div>`,init:initLight},\n{id:'wb',ic:'\u25d1',t:'Nhi\u1ec7t \u0111\u1ed9 m\u00e0u',html:`\n<h1>Nhi\u1ec7t \u0111\u1ed9 m\u00e0u v\u00e0 c\u00e2n b\u1eb1ng tr\u1eafng<\/h1>\n<p class=\"lead\">M\u1ed7i ngu\u1ed3n s\u00e1ng c\u00f3 m\u00e0u ri\u00eang, \u0111o b\u1eb1ng \u0111\u1ed9 Kelvin. \u0110\u00e8n s\u1ee3i \u0111\u1ed1t \u1ea5m cam (~3000K), n\u1eafng tr\u01b0a v\u00e0 \u0111\u00e8n flash trung t\u00ednh (~5600K), tr\u1eddi r\u00e2m ng\u1ea3 xanh (~7000K).<\/p>\n<div class=\"sim\"><div class=\"simrow two\" id=\"wbCtl\"><\/div><div class=\"swrow\" id=\"wbSw\"><\/div><div class=\"verdict\" id=\"wbVer\"><\/div><\/div>\n<div class=\"figrow\"><figure class=\"fig\" data-slot=\"wb_warm\"><\/figure><figure class=\"fig\" data-slot=\"wb_ok\"><\/figure><\/div><p>C\u00e2n b\u1eb1ng tr\u1eafng (WB) tr\u00ean m\u00e1y l\u00e0 ph\u00e9p \"tr\u1eeb m\u00e0u\": \u0111\u1eb7t WB b\u1eb1ng \u0111\u00fang nhi\u1ec7t \u0111\u1ed9 ngu\u1ed3n s\u00e1ng th\u00ec gi\u1ea5y tr\u1eafng ra tr\u1eafng. \u0110\u1eb7t l\u1ec7ch th\u00ec \u1ea3nh \u00e1m m\u00e0u.<\/p>\n<div class=\"tip\">Trong studio, <b>\u0111\u1eebng tr\u1ed9n \u0111\u00e8n kh\u00e1c nhi\u1ec7t \u0111\u1ed9 m\u00e0u<\/b> tr\u00ean c\u00f9ng khu\u00f4n m\u1eb7t (v\u00ed d\u1ee5 LED 5600K v\u1edbi b\u00f3ng tr\u1ea7n 3000K) \u2014 m\u1ed9t b\u00ean m\u00e1 cam, m\u1ed9t b\u00ean m\u00e1 xanh, h\u1eadu k\u1ef3 g\u1ea7n nh\u01b0 kh\u00f4ng c\u1ee9u \u0111\u01b0\u1ee3c.<\/div>`,init:initWB},\n{id:'setups',ic:'\u2726',t:'S\u01a1 \u0111\u1ed3 \u0111\u00e8n ch\u00e2n dung',html:`\n<h1>C\u00e1c s\u01a1 \u0111\u1ed3 \u0111\u00e8n ch\u00e2n dung kinh \u0111i\u1ec3n<\/h1>\n<p class=\"lead\">M\u1ed7i s\u01a1 \u0111\u1ed3 t\u1ea1o m\u1ed9t ki\u1ec3u b\u00f3ng \u0111\u1eb7c tr\u01b0ng tr\u00ean khu\u00f4n m\u1eb7t. B\u1ea5m \u0111\u1ec3 m\u1edf \u0111\u00fang setup trong Studio 3D \u2014 ph\u00f2ng m\u1eb7c \u0111\u1ecbnh \u0111\u00e3 l\u00e0 6 \u00d7 6,5 m, tr\u1ea7n 4 m.<\/p>\n<figure class=\"fig\" data-slot=\"studio_hero\"><\/figure><div class=\"cards\" id=\"setupCards\"><\/div>`,init:initSetups},\n{id:'quiz',ic:'?',t:'Ki\u1ec3m tra nhanh',html:`\n<h1>Ki\u1ec3m tra nhanh<\/h1>\n<p class=\"lead\">M\u01b0\u1eddi c\u00e2u r\u00fat ng\u1eabu nhi\u00ean t\u1eeb ng\u00e2n h\u00e0ng 20 c\u00e2u, m\u1ed7i c\u00e2u c\u00f3 gi\u1ea3i th\u00edch. L\u00e0m xong c\u00f3 th\u1ec3 r\u00fat b\u1ed9 c\u00e2u kh\u00e1c.<\/p>\n<div id=\"quizBox\"><\/div><div class=\"verdict ok\" id=\"quizScore\" style=\"display:none\"><\/div>`,init:initQuiz}\n,{id:'modes',ic:'M',t:'Ch\u1ebf \u0111\u1ed9 ch\u1ee5p M \u00b7 A \u00b7 S \u00b7 P',html:`\n<h1>Ch\u1ebf \u0111\u1ed9 ch\u1ee5p: M, A, S, P<\/h1>\n<p class=\"lead\">V\u00f2ng xoay ch\u1ebf \u0111\u1ed9 quy\u1ebft \u0111\u1ecbnh ai c\u1ea7m l\u00e1i: b\u1ea1n hay m\u00e1y. Ng\u01b0\u1eddi chuy\u00ean nghi\u1ec7p kh\u00f4ng \"l\u00fac n\u00e0o c\u0169ng ch\u1ee5p M\" \u2014 h\u1ecd ch\u1ecdn ch\u1ebf \u0111\u1ed9 nhanh nh\u1ea5t cho t\u00ecnh hu\u1ed1ng.<\/p>\n<table class=\"tbl\"><tr><th>Ch\u1ebf \u0111\u1ed9<\/th><th>B\u1ea1n ch\u1ecdn<\/th><th>M\u00e1y t\u1ef1 ch\u1ecdn<\/th><th>D\u00f9ng khi<\/th><\/tr>\n<tr><td><b>M<\/b> \u2014 th\u1ee7 c\u00f4ng<\/td><td>Kh\u1ea9u, t\u1ed1c, ISO<\/td><td>Kh\u00f4ng g\u00ec c\u1ea3<\/td><td>Studio c\u00f3 flash, \u00e1nh s\u00e1ng c\u1ed1 \u0111\u1ecbnh, ch\u1ee5p h\u00e0ng lo\u1ea1t c\u1ea7n \u0111\u1ed3ng nh\u1ea5t<\/td><\/tr>\n<tr><td><b>A \/ Av<\/b> \u2014 \u01b0u ti\u00ean kh\u1ea9u<\/td><td>Kh\u1ea9u, ISO<\/td><td>T\u1ed1c<\/td><td>Ch\u00e2n dung ngo\u00e0i tr\u1eddi, s\u1ef1 ki\u1ec7n \u2014 b\u1ea1n gi\u1eef quy\u1ec1n xo\u00e1 ph\u00f4ng<\/td><\/tr>\n<tr><td><b>S \/ Tv<\/b> \u2014 \u01b0u ti\u00ean t\u1ed1c<\/td><td>T\u1ed1c, ISO<\/td><td>Kh\u1ea9u<\/td><td>Th\u1ec3 thao, tr\u1ebb con ch\u1ea1y nh\u1ea3y, xe c\u1ed9<\/td><\/tr>\n<tr><td><b>P<\/b> \u2014 ch\u01b0\u01a1ng tr\u00ecnh<\/td><td>ISO (c\u00f3 th\u1ec3 xoay c\u1eb7p kh\u1ea9u\u2013t\u1ed1c)<\/td><td>Kh\u1ea9u v\u00e0 t\u1ed1c<\/td><td>B\u1eaft kho\u1ea3nh kh\u1eafc, ch\u1ee5p h\u1eadu tr\u01b0\u1eddng khi b\u1eadn tay<\/td><\/tr><\/table>\n<h2>V\u00ed d\u1ee5 t\u1eeb c\u00e1c bu\u1ed5i ch\u1ee5p th\u1eadt<\/h2>\n<div class=\"cards\">\n<div class=\"card\"><h3>Profile doanh nghi\u1ec7p trong studio<\/h3><p><b>M \u00b7 f\/8 \u00b7 1\/160 \u00b7 ISO 100 \u00b7 flash.<\/b> \u0110\u00e8n c\u1ed1 \u0111\u1ecbnh n\u00ean m\u1ecdi th\u00f4ng s\u1ed1 kho\u00e1 ch\u1eb7t \u2014 50 nh\u00e2n vi\u00ean ra 50 t\u1ea5m c\u00f9ng \u0111\u1ed9 s\u00e1ng, c\u00f9ng m\u00e0u, h\u1eadu k\u1ef3 \u0111\u1ed3ng b\u1ed9 m\u1ed9t l\u1ea7n.<\/p><\/div>\n<div class=\"card\"><h3>H\u1ed9i ngh\u1ecb, s\u1ef1 ki\u1ec7n trong nh\u00e0<\/h3><p><b>A \u00b7 f\/2.8 \u00b7 ISO Auto t\u1ed1i \u0111a 6400, t\u1ed1c t\u1ed1i thi\u1ec3u 1\/125.<\/b> \u0110\u00e8n s\u00e2n kh\u1ea5u \u0111\u1ed5i li\u00ean t\u1ee5c, m\u00e1y lo ph\u1ea7n t\u1ed1c, b\u1ea1n lo b\u1ed1 c\u1ee5c.<\/p><\/div>\n<div class=\"card\"><h3>Gi\u1ea3i ch\u1ea1y, th\u1ec3 thao<\/h3><p><b>S \u00b7 1\/1000 \u00b7 ISO Auto.<\/b> \u01afu ti\u00ean \u0111\u00f3ng b\u0103ng b\u01b0\u1edbc ch\u00e2n, kh\u1ea9u t\u1ef1 m\u1edf theo l\u01b0\u1ee3ng s\u00e1ng.<\/p><\/div>\n<div class=\"card\"><h3>Quay phim doanh nghi\u1ec7p<\/h3><p><b>M \u00b7 t\u1ed1c = 2 \u00d7 fps<\/b> (1\/50 cho 25fps). T\u1ed1c c\u1ed1 \u0111\u1ecbnh \u0111\u1ec3 chuy\u1ec3n \u0111\u1ed9ng t\u1ef1 nhi\u00ean; d\u00f9ng k\u00ednh ND khi tr\u1eddi s\u00e1ng thay v\u00ec t\u0103ng t\u1ed1c.<\/p><\/div><\/div>\n<div class=\"tip\"><b>M + Auto ISO<\/b> l\u00e0 combo c\u1ee7a d\u00e2n s\u1ef1 ki\u1ec7n: b\u1ea1n kho\u00e1 kh\u1ea9u v\u00e0 t\u1ed1c theo \u00fd \u0111\u1ed3, m\u00e1y ch\u1ec9 \u0111\u1ed5i ISO. Tinh ch\u1ec9nh \u0111\u1ed9 s\u00e1ng b\u1eb1ng n\u00fat b\u00f9 tr\u1eeb ph\u01a1i s\u00e1ng.<\/div>`,ex:'Ch\u1ee5p c\u00f9ng m\u1ed9t bu\u1ed5i h\u1ed9i th\u1ea3o 10 ph\u00fat \u1edf ch\u1ebf \u0111\u1ed9 A, r\u1ed3i 10 ph\u00fat \u1edf M + Auto ISO. So s\u00e1nh s\u1ed1 t\u1ea5m d\u00f9ng \u0111\u01b0\u1ee3c v\u00e0 \u0111\u1ed9 \u0111\u1ed3ng \u0111\u1ec1u m\u00e0u da.'}\n,{id:'meter',ic:'\u25a5',t:'\u0110o s\u00e1ng & histogram',html:`\n<h1>\u0110o s\u00e1ng v\u00e0 \u0111\u1ecdc histogram<\/h1>\n<p class=\"lead\">M\u00e1y \u0111o s\u00e1ng trong m\u00e1y \u1ea3nh lu\u00f4n c\u1ed1 k\u00e9o c\u1ea3nh v\u1ec1 \"x\u00e1m trung t\u00ednh\". Hi\u1ec3u \u0111i\u1ec1u \u0111\u00f3 l\u00e0 hi\u1ec3u v\u00ec sao ph\u00f4ng tr\u1eafng ra x\u00e1m v\u00e0 ph\u00f4ng \u0111en c\u0169ng ra x\u00e1m.<\/p>\n<div class=\"sim\"><canvas id=\"histImg\" width=\"720\" height=\"960\" class=\"sqc\"><\/canvas><canvas id=\"histCv\" width=\"960\" height=\"150\" class=\"histc\"><\/canvas>\n<div class=\"simrow two\" id=\"histCtl\"><\/div><div class=\"verdict\" id=\"histVer\"><\/div><\/div>\n<p>Histogram l\u00e0 bi\u1ec3u \u0111\u1ed3 \u0111\u1ebfm \u0111i\u1ec3m \u1ea3nh theo \u0111\u1ed9 s\u00e1ng: <b>tr\u00e1i l\u00e0 \u0111en, ph\u1ea3i l\u00e0 tr\u1eafng<\/b>. D\u1ed3n s\u00e1t m\u00e9p ph\u1ea3i l\u00e0 ch\u00e1y s\u00e1ng (m\u1ea5t chi ti\u1ebft v\u0129nh vi\u1ec5n), d\u1ed3n s\u00e1t m\u00e9p tr\u00e1i l\u00e0 m\u1ea5t chi ti\u1ebft v\u00f9ng t\u1ed1i. V\u00f9ng \u0111\u1ecf tr\u00ean \u1ea3nh \u1edf tr\u00ean l\u00e0 ch\u1ed7 \u0111\u00e3 ch\u00e1y, xanh l\u00e0 ch\u1ed7 \u0111\u00e3 ch\u1ebft \u0111en.<\/p>\n<h2>C\u00e1c ch\u1ebf \u0111\u1ed9 \u0111o s\u00e1ng<\/h2>\n<table class=\"tbl\"><tr><th>Ch\u1ebf \u0111\u1ed9<\/th><th>C\u00e1ch \u0111o<\/th><th>D\u00f9ng khi<\/th><\/tr>\n<tr><td>Ma tr\u1eadn \/ Evaluative<\/td><td>Chia khung nhi\u1ec1u v\u00f9ng, t\u00ednh trung b\u00ecnh c\u00f3 tr\u1ecdng s\u1ed1<\/td><td>M\u1eb7c \u0111\u1ecbnh cho h\u1ea7u h\u1ebft t\u00ecnh hu\u1ed1ng<\/td><\/tr>\n<tr><td>Trung t\u00e2m<\/td><td>\u01afu ti\u00ean v\u00f9ng gi\u1eefa khung<\/td><td>Ch\u00e2n dung c\u0103n gi\u1eefa, ph\u1ecfng v\u1ea5n<\/td><\/tr>\n<tr><td>\u0110i\u1ec3m (Spot)<\/td><td>Ch\u1ec9 \u0111o 1\u20133% khung<\/td><td>Ng\u01b0\u1eddi \u0111\u1ee9ng ng\u01b0\u1ee3c s\u00e1ng, s\u00e2n kh\u1ea5u t\u1ed1i c\u00f3 \u0111\u00e8n follow<\/td><\/tr><\/table>\n<h2>Khi n\u00e0o b\u00f9 tr\u1eeb ph\u01a1i s\u00e1ng<\/h2>\n<ul><li><b>Ph\u00f4ng tr\u1eafng, tuy\u1ebft, v\u00e1y c\u01b0\u1edbi:<\/b> +1 \u0111\u1ebfn +1,7 EV \u2014 kh\u00f4ng b\u00f9 th\u00ec \u1ea3nh ra x\u00e1m b\u1ea9n.<\/li><li><b>Ph\u00f4ng \u0111en, low-key:<\/b> \u22121 EV \u0111\u1ec3 \u0111en gi\u1eef \u0111\u00fang \u0111en v\u00e0 da kh\u00f4ng ch\u00e1y.<\/li><li><b>Ng\u01b0\u1eddi \u0111\u1ee9ng ng\u01b0\u1ee3c s\u00e1ng c\u1eeda s\u1ed5:<\/b> \u0111o \u0111i\u1ec3m v\u00e0o m\u1eb7t, ho\u1eb7c +1,5 EV.<\/li><\/ul>\n<div class=\"tip\">Trong studio d\u00f9ng flash, m\u00e1y \u0111o s\u00e1ng c\u1ee7a m\u00e1y \u1ea3nh g\u1ea7n nh\u01b0 v\u00f4 d\u1ee5ng \u2014 n\u00f3 kh\u00f4ng \"th\u1ea5y\" tia ch\u1edbp tr\u01b0\u1edbc khi ch\u1ee5p. D\u00f9ng m\u00e1y \u0111o c\u1ea7m tay, ho\u1eb7c ch\u1ee5p th\u1eed r\u1ed3i \u0111\u1ecdc histogram. \u0110\u00f3 l\u00e0 l\u00fd do Studio 3D c\u00f3 m\u00e1y \u0111o s\u00e1ng ri\u00eang.<\/div>`,init:initHist,ex:'Ch\u1ee5p m\u1ed9t chi\u1ebfc \u00e1o tr\u1eafng tr\u00ean n\u1ec1n tr\u1eafng \u1edf ch\u1ebf \u0111\u1ed9 A kh\u00f4ng b\u00f9 tr\u1eeb, r\u1ed3i +0,7, +1,3, +2 EV. M\u1edf histogram t\u1eebng t\u1ea5m v\u00e0 t\u00ecm t\u1ea5m c\u00f3 \u0111\u1ec9nh s\u00e1t m\u00e9p ph\u1ea3i nh\u01b0ng ch\u01b0a ch\u1ea1m.'}\n,{id:'focus',ic:'\u2299',t:'L\u1ea5y n\u00e9t & \u0111\u1ed9 s\u00e2u tr\u01b0\u1eddng \u1ea3nh',html:`\n<h1>L\u1ea5y n\u00e9t v\u00e0 \u0111\u1ed9 s\u00e2u tr\u01b0\u1eddng \u1ea3nh<\/h1>\n<p class=\"lead\">\u1ea2nh \u0111\u1eb9p \u0111\u1ebfn m\u1ea5y m\u00e0 l\u1ec7ch n\u00e9t \u1edf m\u1eaft l\u00e0 b\u1ecf. Hai vi\u1ec7c ph\u1ea3i l\u00e0m ch\u1ee7: ch\u1ecdn \u0111\u00fang ch\u1ebf \u0111\u1ed9 l\u1ea5y n\u00e9t, v\u00e0 bi\u1ebft v\u00f9ng n\u00e9t c\u1ee7a m\u00ecnh d\u00e0y bao nhi\u00eau centimet.<\/p>\n<div class=\"sim\"><div class=\"simrow\" id=\"dofCtl\"><\/div><canvas id=\"dofCv\" width=\"960\" height=\"200\"><\/canvas><div class=\"read\" id=\"dofRead\"><\/div><\/div>\n<p>Th\u1eed ngay: 85mm, f\/1.4, \u0111\u1ee9ng c\u00e1ch 1,5 m \u2014 v\u00f9ng n\u00e9t ch\u1ec9 kho\u1ea3ng 3 cm. M\u1eaft n\u00e9t th\u00ec ch\u00f3p m\u0169i v\u00e0 tai \u0111\u00e3 m\u1edd. \u0110\u00f3ng l\u00ean f\/5.6 l\u00e0 c\u1ea3 khu\u00f4n m\u1eb7t n\u00e9t.<\/p>\n<h2>Ch\u1ebf \u0111\u1ed9 l\u1ea5y n\u00e9t<\/h2>\n<table class=\"tbl\"><tr><th>Ch\u1ebf \u0111\u1ed9<\/th><th>C\u00e1ch ho\u1ea1t \u0111\u1ed9ng<\/th><th>D\u00f9ng khi<\/th><\/tr>\n<tr><td>AF-S \/ One-shot<\/td><td>Kho\u00e1 n\u00e9t khi b\u1ea5m n\u1eeda n\u00fat<\/td><td>Ch\u00e2n dung studio, s\u1ea3n ph\u1ea9m, ch\u1ee7 th\u1ec3 \u0111\u1ee9ng y\u00ean<\/td><\/tr>\n<tr><td>AF-C \/ AI Servo<\/td><td>B\u00e1m n\u00e9t li\u00ean t\u1ee5c<\/td><td>Ng\u01b0\u1eddi di chuy\u1ec3n, s\u1ef1 ki\u1ec7n, th\u1ec3 thao, c\u00f4 d\u00e2u \u0111i v\u00e0o l\u1ec5 \u0111\u01b0\u1eddng<\/td><\/tr>\n<tr><td>Nh\u1eadn di\u1ec7n m\u1eaft (Eye AF)<\/td><td>T\u1ef1 t\u00ecm v\u00e0 b\u00e1m m\u1eaft g\u1ea7n nh\u1ea5t<\/td><td>Ch\u00e2n dung kh\u1ea9u l\u1edbn \u2014 g\u1ea7n nh\u01b0 b\u1eaft bu\u1ed9c \u1edf f\/1.2\u2013f\/2<\/td><\/tr>\n<tr><td>L\u1ea5y n\u00e9t tay (MF)<\/td><td>Xoay v\u00f2ng n\u00e9t, ph\u00f3ng to \u0111\u1ec3 ki\u1ec3m<\/td><td>Macro s\u1ea3n ph\u1ea9m, video, thi\u1ebfu s\u00e1ng n\u1eb7ng<\/td><\/tr><\/table>\n<h2>Kinh nghi\u1ec7m ngh\u1ec1<\/h2>\n<ul><li>Lu\u00f4n l\u1ea5y n\u00e9t v\u00e0o <b>m\u1eaft g\u1ea7n m\u00e1y h\u01a1n<\/b>.<\/li><li><b>L\u1ea5y n\u00e9t b\u1eb1ng n\u00fat sau l\u01b0ng<\/b> (AF-ON): t\u00e1ch l\u1ea5y n\u00e9t kh\u1ecfi n\u00fat ch\u1ee5p \u0111\u1ec3 kh\u00f4ng b\u1ecb m\u00e1y l\u1ea5y n\u00e9t l\u1ea1i khi b\u1ed1 c\u1ee5c l\u1ea1i.<\/li><li>Ch\u1ee5p nh\u00f3m nhi\u1ec1u h\u00e0ng: f\/8 tr\u1edf l\u00ean v\u00e0 l\u1ea5y n\u00e9t v\u00e0o <b>h\u00e0ng th\u1ee9 hai<\/b> \u2014 v\u00f9ng n\u00e9t tr\u1ea3i v\u1ec1 tr\u01b0\u1edbc \u00edt h\u01a1n v\u1ec1 sau.<\/li><li>Ch\u1ee5p profile h\u00e0ng lo\u1ea1t: sau m\u1ed7i l\u1ea7n kh\u00e1ch \u0111\u1ed5i t\u01b0 th\u1ebf, l\u1ea5y n\u00e9t l\u1ea1i d\u00f9 kh\u00e1ch ch\u1ec9 nh\u00edch 5 cm.<\/li><\/ul>`,init:initDof,ex:'D\u00e1n 5 t\u1edd gi\u1ea5y c\u00f3 ch\u1eef c\u00e1ch nhau 10 cm theo chi\u1ec1u s\u00e2u. Ch\u1ee5p \u1edf f\/1.8, f\/4, f\/8 l\u1ea5y n\u00e9t v\u00e0o t\u1edd gi\u1eefa, \u0111\u1ebfm xem m\u1ed7i kh\u1ea9u n\u00e9t \u0111\u01b0\u1ee3c m\u1ea5y t\u1edd v\u00e0 so v\u1edbi m\u00e1y t\u00ednh \u1edf tr\u00ean.'}\n,{id:'lens',ic:'\u25cd',t:'\u1ed0ng k\u00ednh cho t\u1eebng vi\u1ec7c',html:`\n<h1>\u1ed0ng k\u00ednh: ch\u1ecdn g\u00ec cho vi\u1ec7c g\u00ec<\/h1>\n<p class=\"lead\">Th\u00e2n m\u00e1y thay ba b\u1ed1n n\u0103m m\u1ed9t l\u1ea7n; \u1ed1ng k\u00ednh t\u1ed1t d\u00f9ng c\u1ea3 ch\u1ee5c n\u0103m. N\u1ebfu ph\u1ea3i ch\u1ecdn \u0111\u1ea7u t\u01b0, \u0111\u1ea7u t\u01b0 \u1ed1ng tr\u01b0\u1edbc.<\/p>\n<table class=\"tbl\"><tr><th><\/th><th>\u1ed0ng m\u1ed9t ti\u00eau c\u1ef1 (prime)<\/th><th>\u1ed0ng zoom<\/th><\/tr>\n<tr><td>Kh\u1ea9u t\u1ed1i \u0111a<\/td><td>f\/1.2 \u2013 f\/1.8, xo\u00e1 ph\u00f4ng m\u1ea1nh<\/td><td>Th\u01b0\u1eddng f\/2.8 ho\u1eb7c f\/4<\/td><\/tr>\n<tr><td>\u0110\u1ed9 n\u00e9t, ch\u1ea5t \u1ea3nh<\/td><td>Th\u01b0\u1eddng nh\u1ec9nh h\u01a1n<\/td><td>\u1ed0ng zoom cao c\u1ea5p nay r\u1ea5t s\u00e1t<\/td><\/tr>\n<tr><td>T\u1ed1c \u0111\u1ed9 l\u00e0m vi\u1ec7c<\/td><td>Ph\u1ea3i di chuy\u1ec3n ch\u00e2n<\/td><td>\u0110\u1ed5i khung ngay t\u1ea1i ch\u1ed7<\/td><\/tr>\n<tr><td>H\u1ee3p v\u1edbi<\/td><td>Ch\u00e2n dung, thi\u1ebfu s\u00e1ng, phong c\u00e1ch \u0111i\u1ec7n \u1ea3nh<\/td><td>S\u1ef1 ki\u1ec7n, ph\u00f3ng s\u1ef1, doanh nghi\u1ec7p<\/td><\/tr><\/table>\n<h2>B\u1ed9 \u1ed1ng g\u1ee3i \u00fd cho studio ki\u1ec3u K-BLACK<\/h2>\n<table class=\"tbl\"><tr><th>Vi\u1ec7c<\/th><th>\u1ed0ng<\/th><th>V\u00ec sao<\/th><\/tr>\n<tr><td>Profile, ch\u00e2n dung studio<\/td><td>85mm f\/1.8 ho\u1eb7c 70\u2013200 f\/2.8<\/td><td>T\u1ec9 l\u1ec7 m\u1eb7t t\u1ef1 nhi\u00ean; \u0111\u1ee9ng xa l\u00e0m kh\u00e1ch b\u1edbt c\u0103ng<\/td><\/tr>\n<tr><td>\u1ea2nh th\u1ebb, headshot<\/td><td>85\u2013105mm<\/td><td>Kh\u00f4ng m\u00e9o m\u0169i, d\u1ec5 chu\u1ea9n ho\u00e1 khung gi\u1eefa c\u00e1c kh\u00e1ch<\/td><\/tr>\n<tr><td>Ho\u1ea1t \u0111\u1ed9ng c\u00f4ng ty, s\u1ef1 ki\u1ec7n<\/td><td>24\u201370 f\/2.8<\/td><td>T\u1eeb to\u00e0n c\u1ea3nh h\u1ed9i tr\u01b0\u1eddng t\u1edbi n\u1eeda ng\u01b0\u1eddi trong m\u1ed9t \u1ed1ng<\/td><\/tr>\n<tr><td>Kh\u00f4ng gian, v\u0103n ph\u00f2ng<\/td><td>16\u201335mm<\/td><td>G\u00f3c r\u1ed9ng, gi\u1eef \u0111\u01b0\u1eddng th\u1eb3ng ki\u1ebfn tr\u00fac<\/td><\/tr>\n<tr><td>S\u1ea3n ph\u1ea9m nh\u1ecf, chi ti\u1ebft<\/td><td>90\u2013105mm macro<\/td><td>L\u1ea5y n\u00e9t r\u1ea5t g\u1ea7n, n\u00e9t \u0111\u1ec1u t\u1edbi m\u00e9p<\/td><\/tr>\n<tr><td>Phim doanh nghi\u1ec7p<\/td><td>24\u201370 + 35\/50 f\/1.4<\/td><td>Zoom \u0111\u1ec3 ch\u1ea1y vi\u1ec7c, \u1ed1ng fix cho c\u1ea3nh c\u00f3 chi\u1ec1u s\u00e2u<\/td><\/tr><\/table>\n<h2>H\u1ec7 s\u1ed1 crop<\/h2>\n<p>C\u1ea3m bi\u1ebfn APS-C nh\u1ecf h\u01a1n full-frame kho\u1ea3ng 1,5 l\u1ea7n (Canon 1,6). \u1ed0ng 50mm g\u1eafn l\u00ean APS-C cho g\u00f3c nh\u00ecn nh\u01b0 75mm tr\u00ean full-frame. \u0110\u1ed9 xo\u00e1 ph\u00f4ng c\u0169ng gi\u1ea3m: 50mm f\/1.8 tr\u00ean APS-C xo\u00e1 ph\u00f4ng t\u01b0\u01a1ng \u0111\u01b0\u01a1ng kho\u1ea3ng f\/2.8 tr\u00ean full-frame c\u00f9ng khung h\u00ecnh.<\/p>\n<div class=\"tip\">\u1ed0ng g\u00f3c r\u1ed9ng \u0111\u1eb7t s\u00e1t ng\u01b0\u1eddi s\u1ebd k\u00e9o d\u00e0i tay ch\u00e2n v\u00e0 ph\u00f3ng to ph\u1ea7n g\u1ea7n m\u00e1y nh\u1ea5t. D\u00f9ng c\u00f3 ch\u1ee7 \u00fd (\u1ea3nh th\u1eddi trang d\u00e1ng cao, h\u1ea1 m\u00e1y th\u1ea5p) ho\u1eb7c tr\u00e1nh h\u1eb3n (ch\u00e2n dung doanh nh\u00e2n c\u1eadn m\u1eb7t).<\/div>`,ex:'Ch\u1ee5p c\u00f9ng m\u1ed9t ng\u01b0\u1eddi \u1edf c\u00f9ng khung n\u1eeda ng\u01b0\u1eddi b\u1eb1ng 24mm, 50mm v\u00e0 85mm. \u0110\u1eb7t 3 t\u1ea5m c\u1ea1nh nhau v\u00e0 ghi l\u1ea1i thay \u0111\u1ed5i \u1edf m\u0169i, vai v\u00e0 ph\u00f4ng ph\u00eda sau.'}\n,{id:'posing',ic:'\u263a',t:'T\u1ea1o d\u00e1ng & h\u01b0\u1edbng d\u1eabn kh\u00e1ch',html:`\n<h1>T\u1ea1o d\u00e1ng v\u00e0 h\u01b0\u1edbng d\u1eabn ng\u01b0\u1eddi \u0111\u01b0\u1ee3c ch\u1ee5p<\/h1>\n<p class=\"lead\">Kh\u00e1ch doanh nghi\u1ec7p h\u1ea7u h\u1ebft kh\u00f4ng ph\u1ea3i ng\u01b0\u1eddi m\u1eabu. Vi\u1ec7c c\u1ee7a nhi\u1ebfp \u1ea3nh gia l\u00e0 n\u00f3i c\u00e2u ng\u1eafn, c\u1ee5 th\u1ec3, v\u00e0 l\u00e0m m\u1eabu tr\u01b0\u1edbc b\u1eb1ng ch\u00ednh ng\u01b0\u1eddi m\u00ecnh.<\/p>\n<div class=\"cards\">\n<div class=\"card\"><h3>C\u1eb1m<\/h3><p><b>N\u00ean:<\/b> \"\u0110\u01b0a c\u1eb1m ra tr\u01b0\u1edbc, r\u1ed3i h\u1ea1 nh\u1eb9 xu\u1ed1ng.\" \u0110\u01b0\u1eddng h\u00e0m r\u00f5, xo\u00e1 n\u1ecdng c\u1eb1m.<\/p><p><b>Tr\u00e1nh:<\/b> ng\u1eeda c\u1eb1m (l\u1ed9 l\u1ed7 m\u0169i) ho\u1eb7c r\u1ee5t c\u1ed5 khi c\u0103ng th\u1eb3ng.<\/p><\/div>\n<div class=\"card\"><h3>Vai<\/h3><p><b>N\u00ean:<\/b> xoay vai 30\u201345\u00b0 so v\u1edbi m\u00e1y, m\u1eb7t quay l\u1ea1i m\u00e1y. D\u00e1ng g\u1ecdn, c\u00f3 chi\u1ec1u s\u00e2u.<\/p><p><b>Tr\u00e1nh:<\/b> vai vu\u00f4ng g\u00f3c m\u00e1y \u2014 ng\u01b0\u1eddi tr\u00f4ng b\u00e8 ra. Ngo\u1ea1i l\u1ec7: \u1ea3nh th\u1ebb.<\/p><\/div>\n<div class=\"card\"><h3>Tr\u1ecdng t\u00e2m<\/h3><p><b>N\u00ean:<\/b> d\u1ed3n tr\u1ecdng l\u01b0\u1ee3ng v\u00e0o ch\u00e2n sau, ch\u00e2n tr\u01b0\u1edbc ch\u00f9ng g\u1ed1i nh\u1eb9.<\/p><p><b>Tr\u00e1nh:<\/b> \u0111\u1ee9ng nghi\u00eam hai ch\u00e2n \u0111\u1ec1u \u2014 tr\u00f4ng c\u1ee9ng nh\u01b0 \u1ea3nh h\u1ed3 s\u01a1.<\/p><\/div>\n<div class=\"card\"><h3>Tay<\/h3><p><b>N\u00ean:<\/b> cho tay vi\u1ec7c \u0111\u1ec3 l\u00e0m \u2014 ch\u1ec9nh c\u1ed5 tay \u00e1o, c\u1ea7m k\u00ednh, khoanh h\u1edd, \u0111\u00fat m\u1ed9t tay t\u00fai qu\u1ea7n.<\/p><p><b>Tr\u00e1nh:<\/b> tay bu\u00f4ng th\u00f5ng d\u00ednh s\u00e1t th\u00e2n \u2014 b\u1eafp tay tr\u00f4ng to g\u1ea5p r\u01b0\u1ee1i.<\/p><\/div>\n<div class=\"card\"><h3>\u00c1nh m\u1eaft<\/h3><p><b>N\u00ean:<\/b> nh\u00ecn cao h\u01a1n \u1ed1ng k\u00ednh m\u1ed9t ch\u00fat, ngh\u0129 t\u1edbi m\u1ed9t chuy\u1ec7n vui th\u1eadt.<\/p><p><b>Tr\u00e1nh:<\/b> nh\u00ecn ch\u1eb1m ch\u1eb1m \u0111\u00fang t\u00e2m \u1ed1ng v\u1edbi \u00e1nh m\u1eaft \"ch\u1edd b\u1ecb ch\u1ee5p\".<\/p><\/div>\n<div class=\"card\"><h3>N\u1ee5 c\u01b0\u1eddi<\/h3><p><b>N\u00ean:<\/b> tr\u00f2 chuy\u1ec7n, khen c\u1ee5 th\u1ec3, b\u1ea5m ngay sau c\u00e2u \u0111\u00f9a. N\u1ee5 c\u01b0\u1eddi th\u1eadt ch\u1ec9 k\u00e9o d\u00e0i m\u1ed9t gi\u00e2y.<\/p><p><b>Tr\u00e1nh:<\/b> ra l\u1ec7nh \"c\u01b0\u1eddi l\u00ean\" \u2014 ra n\u1ee5 c\u01b0\u1eddi g\u01b0\u1ee3ng.<\/p><\/div>\n<div class=\"card\"><h3>Kho\u1ea3ng h\u1edf<\/h3><p><b>N\u00ean:<\/b> \u0111\u1ec3 m\u1ed9t khe gi\u1eefa c\u00e1nh tay v\u00e0 eo, t\u1ea1o \u0111\u01b0\u1eddng eo v\u00e0 d\u00e1ng thanh.<\/p><p><b>Tr\u00e1nh:<\/b> tay \u00e9p v\u00e0o s\u01b0\u1eddn.<\/p><\/div>\n<div class=\"card\"><h3>D\u00e1ng doanh nh\u00e2n<\/h3><p><b>N\u00ean:<\/b> khoanh tay h\u1edd, ng\u01b0\u1eddi h\u01a1i nghi\u00eang v\u1ec1 ph\u00eda m\u00e1y \u2014 t\u1ef1 tin m\u00e0 g\u1ea7n g\u0169i.<\/p><p><b>Tr\u00e1nh:<\/b> khoanh tay ch\u1eb7t, ng\u1ea3 ng\u01b0\u1eddi ra sau \u2014 tr\u00f4ng ph\u00f2ng th\u1ee7.<\/p><\/div><\/div>\n<h2 class=\"figh\">V\u00ed d\u1ee5 t\u1ea1o d\u00e1ng<\/h2><div class=\"figrow three\"><figure class=\"fig\" data-slot=\"pose_1\"><\/figure><figure class=\"fig\" data-slot=\"pose_2\"><\/figure><figure class=\"fig\" data-slot=\"pose_3\"><\/figure><\/div><h2>T\u1ea1o d\u00e1ng nh\u00f3m<\/h2>\n<ul><li>X\u1ebfp \u0111\u1ea7u ng\u01b0\u1eddi th\u00e0nh c\u00e1c tam gi\u00e1c, kh\u00f4ng \u0111\u1ec3 hai \u0111\u1ea7u n\u1eb1m th\u1eb3ng m\u1ed9t \u0111\u01b0\u1eddng d\u1ecdc.<\/li><li>Ng\u01b0\u1eddi cao \u1edf sau ho\u1eb7c hai r\u00eca; l\u00e3nh \u0111\u1ea1o \u1edf gi\u1eefa, nh\u00edch l\u00ean tr\u01b0\u1edbc n\u1eeda b\u01b0\u1edbc.<\/li><li>H\u00e0ng sau c\u00e1ch h\u00e0ng tr\u01b0\u1edbc 40\u201360 cm, d\u1eb7n nghi\u00eang \u0111\u1ea7u v\u00e0o khe gi\u1eefa hai vai ng\u01b0\u1eddi tr\u01b0\u1edbc.<\/li><li>M\u1ed7i \u0111\u1ed9i h\u00ecnh ch\u1ee5p li\u00ean ti\u1ebfp 5\u20138 t\u1ea5m \u2014 lu\u00f4n c\u00f3 ng\u01b0\u1eddi nh\u1eafm m\u1eaft.<\/li><\/ul>\n<figure class=\"fig\" data-slot=\"pose_group\"><\/figure><div class=\"tip\">C\u00e2u n\u00f3i nhanh khi ch\u1ee5p profile h\u00e0ng lo\u1ea1t: <b>\"Xoay vai v\u1ec1 ph\u00eda c\u1eeda, c\u1eb1m ra tr\u01b0\u1edbc, h\u1ea1 nh\u1eb9, nh\u00ecn em \u2014 ok, th\u1edf ra.\"<\/b> B\u1ed1n c\u00e2u, ba gi\u00e2y, \u1ea3nh ra \u0111\u1ec1u tay.<\/div>`,ex:'Ch\u1ee5p m\u1ed9t \u0111\u1ed3ng nghi\u1ec7p 2 t\u1ea5m: t\u1ea5m \u0111\u1ea7u kh\u00f4ng h\u01b0\u1edbng d\u1eabn g\u00ec, t\u1ea5m sau d\u00f9ng \u0111\u00fang 4 c\u00e2u \u1edf tr\u00ean. \u0110\u01b0a c\u1ea3 hai t\u1ea5m cho ng\u01b0\u1eddi \u0111\u00f3 ch\u1ecdn \u2014 ghi l\u1ea1i h\u1ecd ch\u1ecdn t\u1ea5m n\u00e0o v\u00e0 v\u00ec sao.'}\n,{id:'natlight',ic:'\u263c',t:'\u00c1nh s\u00e1ng t\u1ef1 nhi\u00ean',html:`\n<h1>\u00c1nh s\u00e1ng t\u1ef1 nhi\u00ean<\/h1>\n<p class=\"lead\">M\u1eb7t tr\u1eddi l\u00e0 m\u1ed9t \u0111\u00e8n c\u1ee9ng kh\u1ed5ng l\u1ed3 \u1edf r\u1ea5t xa. M\u00e2y l\u00e0 softbox mi\u1ec5n ph\u00ed. B\u00f3ng r\u00e2m m\u1edf l\u00e0 ph\u00f2ng studio ngo\u00e0i tr\u1eddi.<\/p>\n<table class=\"tbl\"><tr><th>Th\u1eddi \u0111i\u1ec3m<\/th><th>Ch\u1ea5t s\u00e1ng<\/th><th>D\u00f9ng cho<\/th><\/tr>\n<tr><td>Gi\u1edd v\u00e0ng \u2014 m\u1ed9t ti\u1ebfng sau b\u00ecnh minh, tr\u01b0\u1edbc ho\u00e0ng h\u00f4n<\/td><td>\u1ea4m, th\u1ea5p, m\u1ec1m, b\u00f3ng d\u00e0i<\/td><td>Ch\u00e2n dung, pre-wedding, lifestyle<\/td><\/tr>\n<tr><td>Gi\u1edd xanh \u2014 20\u201330 ph\u00fat sau ho\u00e0ng h\u00f4n<\/td><td>L\u1ea1nh, r\u1ea5t m\u1ec1m, tr\u1eddi xanh \u0111\u1eadm<\/td><td>Ki\u1ebfn tr\u00fac l\u00ean \u0111\u00e8n, ch\u00e2n dung k\u1ebft h\u1ee3p flash<\/td><\/tr>\n<tr><td>Tr\u01b0a n\u1eafng g\u1eaft<\/td><td>C\u1ee9ng, r\u1ecdi t\u1eeb tr\u00ean xu\u1ed1ng, h\u1ed1c m\u1eaft \u0111en<\/td><td>T\u00ecm b\u00f3ng r\u00e2m, ho\u1eb7c t\u1ea5m t\u00e1n s\u00e1ng + flash b\u00f9<\/td><\/tr>\n<tr><td>Tr\u1eddi nhi\u1ec1u m\u00e2y<\/td><td>M\u1ec1m, \u0111\u1ec1u, h\u01a1i l\u1ea1nh<\/td><td>Profile ngo\u00e0i tr\u1eddi, s\u1ea3n ph\u1ea9m, \u1ea3nh nh\u00f3m<\/td><\/tr>\n<tr><td>B\u00f3ng r\u00e2m m\u1edf \u2014 m\u00e1i hi\u00ean, c\u1ea1nh to\u00e0 nh\u00e0<\/td><td>M\u1ec1m, c\u00f3 h\u01b0\u1edbng t\u1eeb b\u1ea7u tr\u1eddi<\/td><td>Ch\u00e2n dung gi\u1eefa tr\u01b0a kh\u00f4ng c\u1ea7n \u0111\u00e8n<\/td><\/tr><\/table>\n<div class=\"figrow\"><figure class=\"fig\" data-slot=\"nat_sun\"><\/figure><figure class=\"fig\" data-slot=\"nat_shade\"><\/figure><\/div><h2>\u00c1nh s\u00e1ng c\u1eeda s\u1ed5<\/h2>\n<p>Ng\u01b0\u1eddi \u0111\u1ee9ng c\u00e1ch c\u1eeda s\u1ed5 1\u20132 m, xoay 45\u00b0 v\u1ec1 ph\u00eda c\u1eeda l\u00e0 c\u00f3 ngay ki\u1ec3u Rembrandt m\u1ec1m. C\u00e0ng g\u1ea7n c\u1eeda s\u00e1ng c\u00e0ng m\u1ec1m v\u00e0 ph\u00eda m\u00e1 b\u00ean kia t\u1ed1i c\u00e0ng nhanh. D\u00f9ng r\u00e8m tr\u1eafng m\u1ecfng \u0111\u1ec3 khu\u1ebfch t\u00e1n n\u1eafng chi\u1ebfu th\u1eb3ng.<\/p>\n<h2>T\u1ea5m h\u1eaft s\u00e1ng 5 trong 1<\/h2>\n<table class=\"tbl\"><tr><th>M\u1eb7t<\/th><th>T\u00e1c d\u1ee5ng<\/th><\/tr>\n<tr><td>Tr\u1eafng<\/td><td>B\u00f9 s\u00e1ng m\u1ec1m, t\u1ef1 nhi\u00ean nh\u1ea5t<\/td><\/tr><tr><td>B\u1ea1c<\/td><td>B\u00f9 m\u1ea1nh, t\u1ea1o \u0111\u1ed1m s\u00e1ng trong m\u1eaft r\u00f5<\/td><\/tr><tr><td>V\u00e0ng<\/td><td>L\u00e0m \u1ea5m da \u2014 d\u00f9ng ti\u1ebft ch\u1ebf k\u1ebbo ra m\u00e0u cam<\/td><\/tr><tr><td>\u0110en<\/td><td>\"H\u1eaft \u00e2m\" \u2014 h\u00fat b\u1edbt s\u00e1ng m\u1ed9t b\u00ean \u0111\u1ec3 m\u1eb7t c\u00f3 kh\u1ed1i<\/td><\/tr><tr><td>T\u1ea5m t\u00e1n (m\u1eb7t trong su\u1ed1t)<\/td><td>\u0110\u1eb7t gi\u1eefa n\u1eafng v\u00e0 ng\u01b0\u1eddi \u0111\u1ec3 bi\u1ebfn n\u1eafng g\u1eaft th\u00e0nh s\u00e1ng m\u1ec1m<\/td><\/tr><\/table>\n<div class=\"tip\">C\u00f4ng th\u1ee9c profile ngo\u00e0i tr\u1eddi an to\u00e0n nh\u1ea5t: <b>\u0111\u1eb7t ng\u01b0\u1eddi quay l\u01b0ng v\u1ec1 ph\u00eda m\u1eb7t tr\u1eddi<\/b> cho t\u00f3c s\u00e1ng vi\u1ec1n, r\u1ed3i d\u00f9ng t\u1ea5m h\u1eaft tr\u1eafng b\u00f9 s\u00e1ng v\u00e0o m\u1eb7t t\u1eeb ph\u00eda tr\u01b0\u1edbc d\u01b0\u1edbi.<\/div>`,ex:'Ch\u1ee5p c\u00f9ng m\u1ed9t ng\u01b0\u1eddi \u1edf 3 th\u1eddi \u0111i\u1ec3m trong ng\u00e0y (9h, 12h, 17h) t\u1ea1i c\u00f9ng m\u1ed9t ch\u1ed7. Ghi l\u1ea1i h\u01b0\u1edbng n\u1eafng, \u0111\u1ed9 c\u1ee9ng c\u1ee7a b\u00f3ng v\u00e0 m\u00e0u da \u1edf m\u1ed7i t\u1ea5m.'}\n,{id:'workflow',ic:'\u21c4',t:'RAW, tether & h\u1eadu k\u1ef3',html:`\n<h1>RAW, ch\u1ee5p tether v\u00e0 h\u1eadu k\u1ef3<\/h1>\n<p class=\"lead\">File \u1ea3nh l\u00e0 nguy\u00ean li\u1ec7u. RAW l\u00e0 th\u1ecbt t\u01b0\u01a1i, JPEG l\u00e0 m\u00f3n \u0111\u00e3 n\u1ea5u s\u1eb5n \u2014 ti\u1ec7n, nh\u01b0ng kh\u00f3 ch\u1ebf bi\u1ebfn l\u1ea1i.<\/p>\n<table class=\"tbl\"><tr><th><\/th><th>RAW<\/th><th>JPEG<\/th><\/tr>\n<tr><td>D\u1eef li\u1ec7u m\u00e0u<\/td><td>12\u201314 bit, h\u00e0ng ngh\u00ecn t\u1ef7 m\u00e0u<\/td><td>8 bit, 16,7 tri\u1ec7u m\u00e0u<\/td><\/tr>\n<tr><td>Ch\u1ec9nh c\u00e2n b\u1eb1ng tr\u1eafng<\/td><td>Tu\u1ef3 \u00fd, kh\u00f4ng m\u1ea5t ch\u1ea5t l\u01b0\u1ee3ng<\/td><td>H\u1ea1n ch\u1ebf, d\u1ec5 v\u1ee1 m\u00e0u<\/td><\/tr>\n<tr><td>C\u1ee9u s\u00e1ng t\u1ed1i<\/td><td>\u00b12\u20133 stop<\/td><td>Kho\u1ea3ng \u00b11 stop<\/td><\/tr>\n<tr><td>Dung l\u01b0\u1ee3ng<\/td><td>25\u201360 MB m\u1ed7i t\u1ea5m<\/td><td>5\u201315 MB<\/td><\/tr>\n<tr><td>D\u00f9ng khi<\/td><td>M\u1ecdi bu\u1ed5i ch\u1ee5p c\u00f3 h\u1eadu k\u1ef3<\/td><td>C\u1ea7n g\u1eedi \u1ea3nh ngay t\u1ea1i s\u1ef1 ki\u1ec7n<\/td><\/tr><\/table>\n<h2>Ch\u1ee5p tether<\/h2>\n<p>M\u00e1y n\u1ed1i th\u1eb3ng v\u00e0o m\u00e1y t\u00ednh (Capture One, Lightroom): m\u1ed7i t\u1ea5m hi\u1ec7n ngay tr\u00ean m\u00e0n l\u1edbn. Kh\u00e1ch xem v\u00e0 duy\u1ec7t m\u00e0u t\u1ea1i ch\u1ed7, ekip th\u1ea5y l\u1ed7i n\u00e9t, t\u00f3c r\u1ed1i, n\u1ebfp \u00e1o ngay khi c\u00f2n s\u1eeda \u0111\u01b0\u1ee3c \u2014 thay v\u00ec ph\u00e1t hi\u1ec7n l\u00fac \u0111\u00e3 v\u1ec1. \u0110\u00e2y c\u0169ng l\u00e0 c\u00e1ch \u0111\u1ec3 kh\u00e1ch ch\u1ed1t m\u00e0u tr\u01b0\u1edbc khi thanh to\u00e1n.<\/p>\n<ul><li>D\u00f9ng c\u00e1p USB-C c\u00f3 kho\u00e1, \u0111i d\u00e2y men theo ch\u00e2n \u0111\u00e8n \u0111\u1ec3 kh\u00f4ng ai v\u1ea5p.<\/li><li>T\u1ea1o s\u1eb5n preset m\u00e0u cho bu\u1ed5i ch\u1ee5p, \u00e1p t\u1ef1 \u0111\u1ed9ng khi \u1ea3nh v\u1ec1 m\u00e1y.<\/li><li>\u0110\u1eb7t t\u00ean phi\u00ean theo kh\u00e1ch + ng\u00e0y, ghi song song ra \u1ed5 th\u1ee9 hai.<\/li><\/ul>\n<figure class=\"fig\" data-slot=\"workflow_hero\"><\/figure><h2>Th\u1ee9 t\u1ef1 ch\u1ec9nh \u1ea3nh<\/h2>\n<ol class=\"ol\"><li>C\u00e2n b\u1eb1ng tr\u1eafng \u2014 l\u1ea5y m\u1eabu t\u1eeb th\u1ebb x\u00e1m ch\u1ee5p \u0111\u1ea7u bu\u1ed5i<\/li><li>Ph\u01a1i s\u00e1ng, v\u00f9ng s\u00e1ng, v\u00f9ng t\u1ed1i<\/li><li>T\u01b0\u01a1ng ph\u1ea3n v\u00e0 \u0111\u01b0\u1eddng cong<\/li><li>M\u00e0u t\u1eebng d\u1ea3i (HSL): da, ph\u00f4ng, trang ph\u1ee5c<\/li><li>Retouch da, t\u00f3c l\u1ea1c, n\u1ebfp \u00e1o<\/li><li>L\u00e0m n\u00e9t v\u00e0 xu\u1ea5t file<\/li><\/ol>\n<h2>Th\u00f4ng s\u1ed1 xu\u1ea5t file<\/h2>\n<table class=\"tbl\"><tr><th>\u0110\u00edch \u0111\u1ebfn<\/th><th>Th\u00f4ng s\u1ed1<\/th><\/tr>\n<tr><td>Website<\/td><td>C\u1ea1nh d\u00e0i 2048 px, sRGB, JPEG ch\u1ea5t l\u01b0\u1ee3ng 80\u201385%<\/td><\/tr>\n<tr><td>Facebook, Instagram<\/td><td>1080 \u00d7 1350 px (t\u1ec9 l\u1ec7 4:5), sRGB<\/td><\/tr>\n<tr><td>In \u1ea5n<\/td><td>300 dpi theo k\u00edch th\u01b0\u1edbc th\u1eadt, h\u1ec7 m\u00e0u theo y\u00eau c\u1ea7u nh\u00e0 in<\/td><\/tr>\n<tr><td>\u1ea2nh th\u1ebb, h\u1ed3 s\u01a1<\/td><td>\u0110\u00fang k\u00edch th\u01b0\u1edbc quy \u0111\u1ecbnh (3\u00d74, 4\u00d76 cm\u2026), n\u1ec1n theo quy \u0111\u1ecbnh<\/td><\/tr><\/table>\n<div class=\"tip\">Ch\u1ee5p m\u1ed9t t\u1ea5m c\u00f3 <b>th\u1ebb x\u00e1m<\/b> \u1edf \u0111\u1ea7u m\u1ed7i setup \u00e1nh s\u00e1ng. V\u1ec1 h\u1eadu k\u1ef3 ch\u1ec9 m\u1ed9t c\u00fa b\u1ea5m l\u00e0 \u0111\u1ed3ng b\u1ed9 c\u00e2n b\u1eb1ng tr\u1eafng cho c\u1ea3 tr\u0103m t\u1ea5m.<\/div>`,ex:'Ch\u1ee5p m\u1ed9t t\u1ea5m v\u1eeba RAW v\u1eeba JPEG, c\u1ed1 t\u00ecnh thi\u1ebfu s\u00e1ng 2 stop. K\u00e9o s\u00e1ng c\u1ea3 hai l\u00ean v\u00e0 so v\u00f9ng t\u1ed1i, m\u00e0u da \u1edf \u0111\u1ed9 ph\u00f3ng 100%.'}\n,{id:'session',ic:'\u2611',t:'Quy tr\u00ecnh bu\u1ed5i ch\u1ee5p',html:`\n<h1>Quy tr\u00ecnh m\u1ed9t bu\u1ed5i ch\u1ee5p chuy\u00ean nghi\u1ec7p<\/h1>\n<p class=\"lead\">Kh\u00e1ch kh\u00f4ng nh\u1edb b\u1ea1n d\u00f9ng m\u00e1y g\u00ec. Kh\u00e1ch nh\u1edb bu\u1ed5i ch\u1ee5p c\u00f3 tr\u01a1n tru, c\u00f3 \u0111\u01b0\u1ee3c ch\u0103m s\u00f3c, v\u00e0 \u1ea3nh v\u1ec1 c\u00f3 \u0111\u00fang h\u1eb9n kh\u00f4ng.<\/p>\n<figure class=\"fig\" data-slot=\"session_hero\"><\/figure><div id=\"chk\"><\/div>\n<div class=\"minib\" style=\"max-width:260px\"><button id=\"chkReset\">L\u00e0m m\u1edbi danh s\u00e1ch<\/button><\/div>\n<div class=\"tip\">Danh s\u00e1ch l\u01b0u tr\u00ean tr\u00ecnh duy\u1ec7t \u2014 tick trong l\u00fac chu\u1ea9n b\u1ecb, b\u1ea5m \"L\u00e0m m\u1edbi\" tr\u01b0\u1edbc m\u1ed7i bu\u1ed5i. B\u01b0\u1edbc d\u1ef1ng th\u1eed \u00e1nh s\u00e1ng l\u00e0m ngay trong tab Studio 3D.<\/div>`,init:initChk,ex:'Ch\u1ea1y tr\u1ecdn checklist cho bu\u1ed5i ch\u1ee5p ti\u1ebfp theo. Sau bu\u1ed5i ch\u1ee5p, th\u00eam v\u00e0o s\u1ed5 tay 1 vi\u1ec7c b\u1ea1n \u01b0\u1edbc \u0111\u00e3 l\u00e0m tr\u01b0\u1edbc \u2014 \u0111\u00f3 l\u00e0 d\u00f2ng ti\u1ebfp theo cho checklist c\u1ee7a ri\u00eang b\u1ea1n.'}\n,{id:'fix',ic:'\u26a0',t:'L\u1ed7i th\u01b0\u1eddng g\u1eb7p',html:`\n<h1>L\u1ed7i th\u01b0\u1eddng g\u1eb7p v\u00e0 c\u00e1ch s\u1eeda<\/h1>\n<p class=\"lead\">M\u1ed7i t\u1ea5m h\u1ecfng \u0111\u1ec1u c\u00f3 m\u1ed9t nguy\u00ean nh\u00e2n c\u1ee5 th\u1ec3. Ch\u1ea9n \u0111o\u00e1n \u0111\u00fang th\u00ec s\u1eeda m\u1ea5t m\u1ed9t gi\u00e2y.<\/p>\n<input type=\"text\" id=\"fixQ\" placeholder=\"G\u00f5 \u0111\u1ec3 l\u1ecdc \u2014 v\u00ed d\u1ee5: m\u1edd, \u00e1m, nhi\u1ec5u, ph\u00f4ng, k\u00ednh\">\n<table class=\"tbl\" id=\"fixTbl\" style=\"margin-top:12px\"><\/table>`,init:initFix,ex:'M\u1edf 20 t\u1ea5m h\u1ecfng g\u1ea7n nh\u1ea5t c\u1ee7a b\u1ea1n. G\u00e1n m\u1ed7i t\u1ea5m v\u00e0o m\u1ed9t d\u00f2ng trong b\u1ea3ng \u2014 l\u1ed7i n\u00e0o l\u1eb7p l\u1ea1i nhi\u1ec1u nh\u1ea5t l\u00e0 th\u1ee9 c\u1ea7n luy\u1ec7n \u0111\u1ea7u ti\u00ean.'}\n,{id:'glossary',ic:'Aa',t:'Thu\u1eadt ng\u1eef',html:`\n<h1>Thu\u1eadt ng\u1eef nhi\u1ebfp \u1ea3nh v\u00e0 \u00e1nh s\u00e1ng<\/h1>\n<p class=\"lead\">Nh\u1eefng t\u1eeb b\u1ea1n s\u1ebd nghe m\u1ed7i ng\u00e0y tr\u00ean set ch\u1ee5p \u2014 gi\u1ea3i th\u00edch ng\u1eafn, d\u1ec5 nh\u1edb.<\/p>\n<input type=\"text\" id=\"glQ\" placeholder=\"T\u00ecm thu\u1eadt ng\u1eef \u2014 v\u00ed d\u1ee5: rim, HSS, bokeh\">\n<div id=\"glList\" class=\"gl\"><\/div>`,init:initGloss}\n];\nlet CURL=0;\n\/* ---------- chapters & ordering ---------- *\/\nconst CHAPTERS=['N\u1ec1n t\u1ea3ng m\u00e1y \u1ea3nh','H\u00ecnh \u1ea3nh & con ng\u01b0\u1eddi','\u00c1nh s\u00e1ng','L\u00e0m ngh\u1ec1 chuy\u00ean nghi\u1ec7p','Ki\u1ec3m tra'];\nconst LORDER=[['expo',0],['aperture',0],['shutter',0],['iso',0],['modes',0],['meter',0],['focus',0],['focal',0],['lens',0],['compo',1],['posing',1],['light',2],['natlight',2],['wb',2],['setups',2],['workflow',3],['session',3],['fix',3],['glossary',3],['quiz',4]];\nLESSONS.sort((a,b)=>LORDER.findIndex(x=>x[0]===a.id)-LORDER.findIndex(x=>x[0]===b.id));\nLESSONS.forEach(l=>{const o=LORDER.find(x=>x[0]===l.id);l.ch=o?o[1]:0;});\nconst LEX={expo:'\u0110\u1eb7t m\u00e1y \u1edf ch\u1ebf \u0111\u1ed9 M, ch\u1ee5p c\u00f9ng m\u1ed9t c\u1ea3nh ba l\u1ea7n \u1edf f\/2.8, f\/5.6 v\u00e0 f\/11 \u2014 m\u1ed7i l\u1ea7n t\u1ef1 ch\u1ec9nh t\u1ed1c \u0111\u1ec3 \u0111\u00fang s\u00e1ng. So s\u00e1nh \u0111\u1ed9 m\u1edd ph\u00f4ng v\u00e0 \u0111\u1ed9 nho\u00e8 chuy\u1ec3n \u0111\u1ed9ng.',\n aperture:'Ch\u1ee5p ng\u01b0\u1eddi m\u1eabu \u0111\u1ee9ng c\u00e1ch ph\u00f4ng 0,5 m r\u1ed3i 2,5 m, c\u00f9ng f\/2.8, c\u00f9ng khung h\u00ecnh. Ghi l\u1ea1i kh\u00e1c bi\u1ec7t v\u1ec1 \u0111\u1ed9 m\u1edd v\u00e0 \u0111\u1ed9 s\u00e1ng c\u1ee7a ph\u00f4ng.',\n shutter:'Nh\u1edd ng\u01b0\u1eddi h\u1ea5t t\u00f3c ho\u1eb7c tung gi\u1ea5y v\u1ee5n: ch\u1ee5p \u1edf 1\/60, 1\/250, 1\/1000. T\u00ecm t\u1ed1c th\u1ea5p nh\u1ea5t v\u1eabn \u0111\u00f3ng b\u0103ng \u0111\u01b0\u1ee3c chuy\u1ec3n \u0111\u1ed9ng.',\n iso:'Ch\u1ee5p m\u1ed9t g\u00f3c t\u1ed1i \u1edf ISO 400, 1600, 6400; ph\u00f3ng 100% v\u00f9ng t\u1ed1i \u0111\u1ec3 t\u00ecm ng\u01b0\u1ee1ng nhi\u1ec5u b\u1ea1n ch\u1ea5p nh\u1eadn \u0111\u01b0\u1ee3c v\u1edbi m\u00e1y c\u1ee7a m\u00ecnh.',\n focal:'Gi\u1eef khu\u00f4n m\u1eb7t c\u00f9ng k\u00edch th\u01b0\u1edbc trong khung, ch\u1ee5p b\u1eb1ng 35mm (\u0111\u1ee9ng g\u1ea7n) v\u00e0 85mm (l\u00f9i xa). So s\u00e1nh m\u0169i, tai v\u00e0 ph\u00f4ng ph\u00eda sau.',\n compo:'Ch\u1ee5p 10 t\u1ea5m c\u00f9ng m\u1ed9t ch\u1ee7 th\u1ec3: 5 t\u1ea5m theo 1\/3, 5 t\u1ea5m c\u0103n gi\u1eefa c\u00f3 ch\u1ee7 \u00fd. Ch\u1ecdn 2 t\u1ea5m t\u1ed1t nh\u1ea5t v\u00e0 vi\u1ebft m\u1ed9t c\u00e2u gi\u1ea3i th\u00edch v\u00ec sao.',\n light:'\u0110\u1eb7t softbox c\u00e1ch m\u1eb7t 0,8 m r\u1ed3i 2,5 m, ch\u1ec9nh c\u00f4ng su\u1ea5t \u0111\u1ec3 m\u1eb7t s\u00e1ng nh\u01b0 nhau. Quan s\u00e1t \u0111\u1ed9 m\u1ec1m c\u1ee7a b\u00f3ng m\u0169i v\u00e0 \u0111\u1ed9 t\u1ed1i c\u1ee7a ph\u00f4ng.',\n wb:'Ch\u1ee5p t\u1edd gi\u1ea5y tr\u1eafng d\u01b0\u1edbi \u0111\u00e8n ph\u00f2ng v\u1edbi WB Auto, Daylight, Tungsten v\u00e0 WB t\u00f9y ch\u1ec9nh \u0111o t\u1eeb ch\u00ednh t\u1edd gi\u1ea5y. K\u1ebft qu\u1ea3 n\u00e0o trung th\u1ef1c nh\u1ea5t?',\n setups:'M\u1edf t\u1eebng setup trong Studio 3D, xem qua \u1ed1ng k\u00ednh, t\u1ea3i s\u01a1 \u0111\u1ed3 \u0111\u00e8n \u2014 r\u1ed3i d\u1ef1ng l\u1ea1i ngo\u00e0i th\u1ef1c t\u1ebf v\u00e0 so \u1ea3nh th\u1eadt v\u1edbi b\u1ea3n xem tr\u01b0\u1edbc.'};\nLESSONS.forEach(l=>{if(!l.ex&&LEX[l.id])l.ex=LEX[l.id];});\n\/* ---------- histogram helper ---------- *\/\nfunction histogramOf(ctx,W,H,step){let d;try{d=ctx.getImageData(0,0,W,H);}catch(e){return null;}if(!d||!d.data)return null;const h=new Array(256).fill(0);let hi=0,lo=0,n=0;const px=d.data;step=step||2;for(let y=0;y<H;y+=step)for(let x=0;x<W;x+=step){const i=(y*W+x)*4;const l=Math.round(.2126*px[i]+.7152*px[i+1]+.0722*px[i+2]);h[l]++;n++;if(px[i]>=252||px[i+1]>=252||px[i+2]>=252)hi++;if(l<=4)lo++;}return {h,hi:hi\/n,lo:lo\/n,img:d};}\nfunction drawHist(cv,res){const x=ctx2d(cv);if(!x||!res)return;const W=cv.width,H=cv.height;x.fillStyle='#0b0f1a';x.fillRect(0,0,W,H);x.strokeStyle='#1f2a45';x.beginPath();for(let i=1;i<4;i++){x.moveTo(W*i\/4,0);x.lineTo(W*i\/4,H);}x.stroke();const mx=Math.max.apply(null,res.h.slice(1,255))||1;x.fillStyle='rgba(233,238,247,.85)';for(let i=0;i<256;i++){const v=Math.min(1,res.h[i]\/mx);x.fillRect(i\/256*W,H-v*(H-8),W\/256+1,v*(H-8));}\n if(res.hi>0.003){x.fillStyle='#ff5a5a';x.fillRect(W-6,0,6,H);}if(res.lo>0.003){x.fillStyle='#5a8cff';x.fillRect(0,0,6,H);}x.fillStyle='#8e9ab3';x.font='600 13px \"Be Vietnam Pro\"';x.fillText('\u0111en',10,16);x.fillText('tr\u1eafng',W-44,16);}\n\/* ---------- metering & histogram lesson ---------- *\/\n\/* ---------- depth of field calculator ---------- *\/\nfunction fmtLen(mm){return mm<1000?(mm\/10).toFixed(mm<100?1:0)+' cm':(mm\/1000).toFixed(2)+' m';}\nfunction initDof(){const S={f:85,N:2.8,s:2,ff:true};const C=$('dofCtl');\n C.appendChild(selc('Ti\u00eau c\u1ef1',[[24,'24mm'],[35,'35mm'],[50,'50mm'],[85,'85mm'],[105,'105mm'],[135,'135mm'],[200,'200mm']],S.f,v=>{S.f=+v;draw();}));\n C.appendChild(selc('Kh\u1ea9u',[1.4,1.8,2,2.8,4,5.6,8,11,16].map(a=>[a,'f\/'+a]),S.N,v=>{S.N=+v;draw();}));\n C.appendChild(selc('C\u1ea3m bi\u1ebfn',[[1,'Full-frame'],[0,'APS-C']],1,v=>{S.ff=v==='1';draw();}));\n const ds=sld('Kho\u1ea3ng c\u00e1ch l\u1ea5y n\u00e9t',0.5,20,0.1,S.s,v=>v.toFixed(1)+' m',v=>{S.s=v;draw();});ds.style.gridColumn='1 \/ 4';C.appendChild(ds);\n function draw(){const c=S.ff?0.03:0.02;const f=S.f;const s=S.s*1000;const H=f*f\/(S.N*c)+f;const near=s*(H-f)\/(H+s-2*f);const far=s<H?s*(H-f)\/(H-s):Infinity;const tot=far===Infinity?Infinity:far-near;\n  $('dofRead').innerHTML='N\u00e9t t\u1eeb <b>'+(near\/1000).toFixed(2)+' m<\/b> \u0111\u1ebfn <b>'+(far===Infinity?'v\u00f4 c\u1ef1c':(far\/1000).toFixed(2)+' m')+'<\/b> &nbsp; V\u00f9ng n\u00e9t <b>'+(tot===Infinity?'v\u00f4 c\u1ef1c':fmtLen(tot))+'<\/b> &nbsp; Si\u00eau ti\u00eau c\u1ef1 <b>'+(H\/1000).toFixed(1)+' m<\/b>';\n  const x=ctx2d($('dofCv'));if(!x)return;const W=960,Hh=200;const maxM=far===Infinity?Math.max(S.s*2.2,H\/1000*1.2):Math.max(S.s*1.6,far\/1000*1.15);const X=m=>60+m\/maxM*(W-100);\n  x.fillStyle='#0d1322';x.fillRect(0,0,W,Hh);x.strokeStyle='#2a3858';x.beginPath();x.moveTo(60,140);x.lineTo(W-30,140);x.stroke();x.fillStyle='#8e9ab3';x.font='500 13px \"Be Vietnam Pro\"';const stp=maxM>10?5:maxM>4?1:0.5;for(let m=0;m<=maxM;m+=stp){x.fillRect(X(m),136,1,8);x.fillText(m+' m',X(m)-10,162);}\n  const x1=X(near\/1000),x2=far===Infinity?W-30:X(far\/1000);x.fillStyle='rgba(255,178,89,.22)';x.fillRect(x1,40,Math.max(2,x2-x1),96);x.strokeStyle='#ffb259';x.strokeRect(x1,40,Math.max(2,x2-x1),96);\n  x.fillStyle='#fff';x.beginPath();x.moveTo(40,112);x.lineTo(60,100);x.lineTo(60,124);x.fill();x.fillStyle='#d9b59c';x.beginPath();x.arc(X(S.s),88,12,0,7);x.fill();x.fillRect(X(S.s)-9,100,18,36);x.fillStyle='#ffb259';x.font='600 14px \"Be Vietnam Pro\"';x.fillText('v\u00f9ng n\u00e9t',Math.min(x1+6,W-110),34);}\n draw();}\n\/* ---------- session checklist ---------- *\/\nconst CHK=[['Tr\u01b0\u1edbc bu\u1ed5i ch\u1ee5p (1\u20133 ng\u00e0y)',['Ch\u1ed1t brief, moodboard v\u00e0 danh s\u00e1ch khung h\u00ecnh v\u1edbi kh\u00e1ch','G\u1eedi h\u01b0\u1edbng d\u1eabn trang ph\u1ee5c: tr\u00e1nh s\u1ecdc nh\u1ecf, logo to; mang 2\u20133 b\u1ed9','D\u1ef1ng th\u1eed \u00e1nh s\u00e1ng trong Studio 3D, t\u1ea3i s\u01a1 \u0111\u1ed3 \u0111\u00e8n g\u1eedi ekip','S\u1ea1c to\u00e0n b\u1ed9 pin m\u00e1y, pin \u0111\u00e8n, pin b\u1ed9 k\u00edch','Format th\u1ebb nh\u1edb, ki\u1ec3m tra \u1ed5 c\u1ee9ng d\u1ef1 ph\u00f2ng v\u00e0 c\u00e1p tether','X\u00e1c nh\u1eadn l\u1ecbch, \u0111\u1ecba ch\u1ec9, ng\u01b0\u1eddi li\u00ean h\u1ec7 t\u1ea1i ch\u1ed7']],\n ['T\u1ea1i hi\u1ec7n tr\u01b0\u1eddng',['D\u00e1n d\u1ea5u X v\u1ecb tr\u00ed ch\u00e2n \u0111\u00e8n, ch\u1ee7 th\u1ec3 v\u00e0 m\u00e1y theo s\u01a1 \u0111\u1ed3','Ch\u1ee5p th\u1eed k\u00e8m th\u1ebb x\u00e1m cho t\u1eebng setup \u00e1nh s\u00e1ng','Ki\u1ec3m tra histogram, ph\u00f3ng 100% v\u00e0o m\u1eaft','B\u1eadt tether, duy\u1ec7t m\u00e0u c\u00f9ng kh\u00e1ch tr\u00ean m\u00e0n l\u1edbn','Ch\u1ee5p d\u01b0 20% so v\u1edbi danh s\u00e1ch khung h\u00ecnh','Ch\u1ee5p h\u1eadu tr\u01b0\u1eddng cho k\u00eanh K-BLACK']],\n ['Sau bu\u1ed5i ch\u1ee5p',['Sao l\u01b0u ra hai n\u01a1i ngay trong ng\u00e0y','L\u1ecdc \u1ea3nh trong 24\u201348 gi\u1edd, g\u1eedi kh\u00e1ch b\u1ea3n xem tr\u01b0\u1edbc','Ch\u1ec9nh m\u00e0u theo preset \u0111\u00e3 duy\u1ec7t v\u1edbi kh\u00e1ch','Retouch theo m\u1ee9c g\u00f3i \u0111\u00e3 b\u00e1o gi\u00e1','Giao file \u0111\u00fang \u0111\u1ecbnh d\u1ea1ng, \u0111\u00fang h\u1eb9n','Xin ph\u1ea3n h\u1ed3i v\u00e0 xin ph\u00e9p d\u00f9ng \u1ea3nh l\u00e0m portfolio']]];\nfunction initChk(){let st={};try{st=JSON.parse(localStorage.getItem('kblack_lab_chk')||'{}');}catch(e){}const box=$('chk');const save=()=>{try{localStorage.setItem('kblack_lab_chk',JSON.stringify(st));}catch(e){}};\n function draw(){box.innerHTML='';CHK.forEach((ph,pi)=>{const done=ph[1].filter((_,i)=>st[pi+'_'+i]).length;const sec=el('div','chkp','<h2>'+ph[0]+' <small>'+done+'\/'+ph[1].length+'<\/small><\/h2>');ph[1].forEach((t,i)=>{const k=pi+'_'+i;const lb=el('label','chki'+(st[k]?' on':''));const cb=document.createElement('input');cb.type='checkbox';cb.checked=!!st[k];cb.onchange=()=>{st[k]=cb.checked;save();draw();};lb.appendChild(cb);lb.appendChild(el('span',null,t));sec.appendChild(lb);});box.appendChild(sec);});}\n $('chkReset').onclick=()=>{st={};save();draw();toast('\u0110\u00e3 l\u00e0m m\u1edbi danh s\u00e1ch');};draw();}\n\/* ---------- troubleshooting ---------- *\/\nconst FIXES=[['\u1ea2nh m\u1edd to\u00e0n b\u1ed9','Rung tay, t\u1ed1c qu\u00e1 ch\u1eadm','T\u1ed1c \u2265 1\/ti\u00eau c\u1ef1, b\u1eadt ch\u1ed1ng rung, d\u00f9ng ch\u00e2n m\u00e1y'],['M\u1eaft kh\u00f4ng n\u00e9t, tai l\u1ea1i n\u00e9t','L\u1ea5y n\u00e9t tr\u01b0\u1ee3t ra sau khi m\u1edf kh\u1ea9u l\u1edbn','B\u1eadt nh\u1eadn di\u1ec7n m\u1eaft, \u0111\u00f3ng kh\u1ea9u 1 stop, l\u1ea5y n\u00e9t l\u1ea1i sau m\u1ed7i l\u1ea7n kh\u00e1ch \u0111\u1ed5i t\u01b0 th\u1ebf'],['V\u1eadt chuy\u1ec3n \u0111\u1ed9ng b\u1ecb nho\u00e8','T\u1ed1c qu\u00e1 ch\u1eadm so v\u1edbi chuy\u1ec3n \u0111\u1ed9ng','1\/500 tr\u1edf l\u00ean, ho\u1eb7c d\u00f9ng flash \u0111\u1ec3 \u0111\u00f3ng b\u0103ng'],['\u1ea2nh nhi\u1ec5u h\u1ea1t','ISO cao, ho\u1eb7c thi\u1ebfu s\u00e1ng r\u1ed3i k\u00e9o s\u00e1ng l\u00ean','Th\u00eam s\u00e1ng th\u1eadt (\u0111\u00e8n), m\u1edf kh\u1ea9u, ph\u01a1i s\u00e1ng \u0111\u00fang ngay t\u1eeb \u0111\u1ea7u'],['Da \u00e1m cam ho\u1eb7c \u00e1m xanh','WB l\u1ec7ch ngu\u1ed3n s\u00e1ng, tr\u1ed9n \u0111\u00e8n kh\u00e1c nhi\u1ec7t \u0111\u1ed9 m\u00e0u','\u0110\u1eb7t WB theo Kelvin, ch\u1ee5p th\u1ebb x\u00e1m, kh\u00f4ng tr\u1ed9n ngu\u1ed3n s\u00e1ng tr\u00ean m\u1eb7t'],['V\u00f9ng s\u00e1ng ch\u00e1y tr\u1eafng','D\u01b0 s\u00e1ng, \u0111\u00e8n qu\u00e1 g\u1ea7n','Gi\u1ea3m 1 stop c\u00f4ng su\u1ea5t, l\u00f9i \u0111\u00e8n, ki\u1ec3m tra histogram'],['Ph\u00f4ng tr\u1eafng ra x\u00e1m','M\u00e1y \u0111o s\u00e1ng k\u00e9o c\u1ea3nh v\u1ec1 x\u00e1m trung t\u00ednh','B\u00f9 +1 EV ho\u1eb7c chi\u1ebfu \u0111\u00e8n ri\u00eang cho ph\u00f4ng'],['V\u1ec7t \u0111en ngang \u1ea3nh khi d\u00f9ng flash','V\u01b0\u1ee3t t\u1ed1c \u0111\u1ed3ng b\u1ed9','H\u1ea1 v\u1ec1 1\/200\u20131\/250 ho\u1eb7c b\u1eadt HSS'],['B\u00f3ng ng\u01b0\u1eddi \u0111\u1ed5 l\u00ean ph\u00f4ng','Ng\u01b0\u1eddi \u0111\u1ee9ng s\u00e1t ph\u00f4ng, \u0111\u00e8n \u0111\u1eb7t th\u1ea5p','K\u00e9o ng\u01b0\u1eddi ra xa ph\u00f4ng \u00edt nh\u1ea5t 1,5 m, n\u00e2ng \u0111\u00e8n cao h\u01a1n'],['H\u1ed1c m\u1eaft t\u1ed1i','\u0110\u00e8n qu\u00e1 cao, ho\u1eb7c n\u1eafng \u0111\u1ec9nh \u0111\u1ea7u','H\u1ea1 \u0111\u00e8n, th\u00eam fill ph\u00eda d\u01b0\u1edbi ho\u1eb7c t\u1ea5m h\u1eaft'],['M\u1eaft k\u00ednh b\u1ecb lo\u00e1 \u0111\u00e8n','\u0110\u00e8n n\u1eb1m \u0111\u00fang g\u00f3c ph\u1ea3n x\u1ea1 c\u1ee7a m\u1eaft k\u00ednh','N\u00e2ng \u0111\u00e8n cao h\u01a1n ho\u1eb7c \u0111\u01b0a sang b\u00ean th\u00eam 15\u201320\u00b0, h\u1ea1 nh\u1eb9 g\u1ecdng k\u00ednh'],['M\u1eb7t b\u00f3ng d\u1ea7u','Da ph\u1ea3n chi\u1ebfu ngu\u1ed3n s\u00e1ng nh\u1ecf, c\u1ee9ng','Th\u1ea5m d\u1ea7u, ph\u1ee7 ph\u1ea5n, d\u00f9ng ngu\u1ed3n s\u00e1ng to h\u01a1n'],['Nh\u00f3m \u0111\u00f4ng, ng\u01b0\u1eddi \u0111\u1ee9ng r\u00eca t\u1ed1i','\u0110\u00e8n \u0111\u1eb7t g\u1ea7n, ngu\u1ed3n s\u00e1ng nh\u1ecf','L\u00f9i \u0111\u00e8n xa, d\u00f9ng d\u00f9 l\u1edbn, \u0111\u1eb7t hai \u0111\u00e8n ch\u00e9o hai b\u00ean m\u00e1y'],['M\u00e0u kh\u00e1c nhau gi\u1eefa c\u00e1c t\u1ea5m','\u00c1nh s\u00e1ng m\u00f4i tr\u01b0\u1eddng thay \u0111\u1ed5i, \u0111\u00e8n kh\u00f4ng \u1ed5n \u0111\u1ecbnh','T\u1eaft \u0111\u00e8n ph\u00f2ng, kho\u00e1 WB, ch\u1ee5p th\u1ebb x\u00e1m m\u1ed7i setup'],['Kh\u00f4ng c\u00f3 \u0111\u1ed1m s\u00e1ng trong m\u1eaft','\u0110\u00e8n ch\u00ednh qu\u00e1 th\u1ea5p ho\u1eb7c qu\u00e1 l\u1ec7ch','\u0110\u01b0a \u0111\u00e8n v\u1ec1 ph\u00eda tr\u01b0\u1edbc, cao h\u01a1n m\u1eaft kho\u1ea3ng 30\u201345\u00b0'],['\u1ea2nh t\u1ed1i g\u00f3c (vignette)','Loa che n\u1eafng sai, kh\u1ea9u m\u1edf l\u1edbn, \u1ed1ng r\u1ed9ng','\u0110\u00f3ng kh\u1ea9u 1\u20132 stop, d\u00f9ng \u0111\u00fang loa che, b\u1eadt hi\u1ec7u ch\u1ec9nh \u1ed1ng k\u00ednh']];\nfunction initFix(){const T=$('fixTbl');const q=$('fixQ');const norm=s=>s.toLowerCase().normalize('NFD').replace(\/[\\u0300-\\u036f]\/g,'').replace(\/\u0111\/g,'d');\n function draw(){const k=norm(q.value.trim());const rows=FIXES.filter(r=>!k||norm(r.join(' ')).indexOf(k)>=0);T.innerHTML='<tr><th>Hi\u1ec7n t\u01b0\u1ee3ng<\/th><th>Nguy\u00ean nh\u00e2n<\/th><th>C\u00e1ch s\u1eeda<\/th><\/tr>'+(rows.length?rows.map(r=>'<tr><td><b>'+r[0]+'<\/b><\/td><td>'+r[1]+'<\/td><td>'+r[2]+'<\/td><\/tr>').join(''):'<tr><td colspan=\"3\">Kh\u00f4ng c\u00f3 l\u1ed7i n\u00e0o kh\u1edbp \u2014 th\u1eed t\u1eeb kho\u00e1 kh\u00e1c.<\/td><\/tr>');}\n q.oninput=draw;draw();}\n\/* ---------- glossary ---------- *\/\nconst GLOSS=[['Kh\u1ea9u \u0111\u1ed9 (aperture)','\u0110\u1ed9 m\u1edf c\u1ee7a l\u00e1 kh\u1ea9u trong \u1ed1ng k\u00ednh, ghi b\u1eb1ng s\u1ed1 f. S\u1ed1 f c\u00e0ng nh\u1ecf, l\u1ed7 c\u00e0ng to.'],['Stop','M\u1ed9t b\u01b0\u1edbc g\u1ea5p \u0111\u00f4i ho\u1eb7c gi\u1ea3m n\u1eeda l\u01b0\u1ee3ng s\u00e1ng.'],['EV','\u0110\u01a1n v\u1ecb \u0111o m\u1ee9c ph\u01a1i s\u00e1ng; +1 EV s\u00e1ng g\u1ea5p \u0111\u00f4i.'],['Bokeh','Ch\u1ea5t l\u01b0\u1ee3ng v\u00f9ng m\u1edd ngo\u00e0i v\u00f9ng n\u00e9t.'],['\u0110\u1ed9 s\u00e2u tr\u01b0\u1eddng \u1ea3nh (DOF)','Kho\u1ea3ng t\u1eeb g\u1ea7n \u0111\u1ebfn xa tr\u00f4ng n\u00e9t trong \u1ea3nh.'],['Si\u00eau ti\u00eau c\u1ef1 (hyperfocal)','Kho\u1ea3ng l\u1ea5y n\u00e9t gi\u00fap v\u00f9ng n\u00e9t k\u00e9o d\u00e0i t\u1edbi v\u00f4 c\u1ef1c.'],['T\u1ed1c \u0111\u1ed3ng b\u1ed9 (sync speed)','T\u1ed1c nhanh nh\u1ea5t flash c\u00f2n ph\u1ee7 k\u00edn c\u1ea3m bi\u1ebfn, th\u01b0\u1eddng 1\/200\u20131\/250.'],['HSS','Ch\u1ebf \u0111\u1ed9 flash t\u1ed1c cao, cho ph\u00e9p v\u01b0\u1ee3t t\u1ed1c \u0111\u1ed3ng b\u1ed9 nh\u01b0ng gi\u1ea3m c\u00f4ng su\u1ea5t.'],['Guide number (GN)','Ch\u1ec9 s\u1ed1 c\u00f4ng su\u1ea5t flash: GN = kho\u1ea3ng c\u00e1ch \u00d7 s\u1ed1 f \u1edf ISO 100.'],['Key light','\u0110\u00e8n ch\u00ednh, quy\u1ebft \u0111\u1ecbnh h\u01b0\u1edbng s\u00e1ng v\u00e0 b\u00f3ng.'],['Fill light','\u0110\u00e8n b\u00f9, l\u00e0m m\u1edf v\u00f9ng t\u1ed1i do \u0111\u00e8n ch\u00ednh t\u1ea1o ra.'],['Rim light','\u0110\u00e8n vi\u1ec1n \u0111\u1eb7t sau l\u01b0ng, t\u1ea1o \u0111\u01b0\u1eddng s\u00e1ng t\u00e1ch vai v\u00e0 t\u00f3c kh\u1ecfi n\u1ec1n.'],['Kicker','\u0110\u00e8n vi\u1ec1n t\u1eeb sau-b\u00ean, chi\u1ebfu l\u01b0\u1edbt m\u1ed9t b\u00ean m\u00e1 ho\u1eb7c h\u00e0m.'],['Hair light','\u0110\u00e8n t\u00f3c, th\u01b0\u1eddng treo boom tr\u00ean \u0111\u1ea7u h\u01a1i l\u00f9i v\u1ec1 sau.'],['Background light','\u0110\u00e8n chi\u1ebfu ri\u00eang cho ph\u00f4ng n\u1ec1n.'],['T\u1ec9 l\u1ec7 s\u00e1ng (lighting ratio)','T\u1ec9 l\u1ec7 gi\u1eefa key v\u00e0 fill, v\u00ed d\u1ee5 4:1 l\u00e0 ch\u00eanh 2 stop.'],['Softbox','H\u1ed9p t\u1ea3n s\u00e1ng ch\u1eef nh\u1eadt, cho \u00e1nh s\u00e1ng m\u1ec1m c\u00f3 h\u01b0\u1edbng.'],['Octabox','H\u1ed9p t\u1ea3n s\u00e1ng b\u00e1t gi\u00e1c, \u0111\u1ed1m s\u00e1ng trong m\u1eaft tr\u00f2n t\u1ef1 nhi\u00ean.'],['Stripbox','Softbox d\u00e0i h\u1eb9p, h\u1ee3p l\u00e0m rim ho\u1eb7c s\u00e1ng d\u1ea3i tr\u00ean s\u1ea3n ph\u1ea9m.'],['Parabolic','Ch\u00f3a s\u00e2u d\u1ea1ng parabol, s\u00e1ng t\u1eadp trung m\u00e0 v\u1eabn m\u1ec1m.'],['Beauty dish','Ch\u00f3a n\u00f4ng c\u00f3 t\u1ea5m ch\u1eafn gi\u1eefa, s\u00e1ng m\u1ec1m v\u1eeba, c\u00f3 t\u01b0\u01a1ng ph\u1ea3n.'],['T\u1ed5 ong (grid)','T\u1ea5m l\u01b0\u1edbi g\u1eafn tr\u01b0\u1edbc t\u1ea3n s\u00e1ng, khoanh v\u00f9ng s\u00e1ng, ch\u1ed1ng lan.'],['Barn doors','B\u1ed1n c\u00e1nh che tr\u00ean \u0111\u00e8n spot \u0111\u1ec3 c\u1eaft v\u1ec7t s\u00e1ng.'],['V\u1ea9y \u0111\u00e8n (feathering)','Xoay \u0111\u00e8n \u0111\u1ec3 m\u00e9p ch\u00f9m s\u00e1ng ch\u1ea1m ch\u1ee7 th\u1ec3, cho s\u00e1ng m\u1ec1m v\u00e0 \u0111\u1ec1u h\u01a1n.'],['Lu\u1eadt b\u00ecnh ph\u01b0\u01a1ng ngh\u1ecbch \u0111\u1ea3o','G\u1ea5p \u0111\u00f4i kho\u1ea3ng c\u00e1ch, \u00e1nh s\u00e1ng c\u00f2n m\u1ed9t ph\u1ea7n t\u01b0.'],['Catchlight','\u0110\u1ed1m s\u00e1ng ph\u1ea3n chi\u1ebfu \u0111\u00e8n trong m\u1eaft, l\u00e0m m\u1eaft c\u00f3 h\u1ed3n.'],['Rembrandt','S\u01a1 \u0111\u1ed3 \u0111\u00e8n 45\u00b0, t\u1ea1o tam gi\u00e1c s\u00e1ng tr\u00ean m\u00e1 ph\u00eda t\u1ed1i.'],['Butterfly','\u0110\u00e8n tr\u01b0\u1edbc m\u1eb7t v\u00e0 cao, b\u00f3ng h\u00ecnh c\u00e1nh b\u01b0\u1edbm d\u01b0\u1edbi m\u0169i.'],['Clamshell','Hai \u0111\u00e8n k\u1eb9p tr\u00ean d\u01b0\u1edbi, \u1ea3nh beauty da m\u1ecbn.'],['High-key','\u1ea2nh t\u00f4ng s\u00e1ng, n\u1ec1n tr\u1eafng, \u00edt b\u00f3ng.'],['Low-key','\u1ea2nh t\u00f4ng t\u1ed1i, n\u1ec1n \u0111en, s\u00e1ng khoanh v\u00f9ng.'],['Nhi\u1ec7t \u0111\u1ed9 m\u00e0u (Kelvin)','M\u00e0u c\u1ee7a ngu\u1ed3n s\u00e1ng: th\u1ea5p l\u00e0 \u1ea5m cam, cao l\u00e0 l\u1ea1nh xanh.'],['C\u00e2n b\u1eb1ng tr\u1eafng (WB)','Thi\u1ebft l\u1eadp gi\u00fap v\u1eadt tr\u1eafng ra \u0111\u00fang tr\u1eafng d\u01b0\u1edbi ngu\u1ed3n s\u00e1ng hi\u1ec7n t\u1ea1i.'],['Histogram','Bi\u1ec3u \u0111\u1ed3 ph\u00e2n b\u1ed1 \u0111\u1ed9 s\u00e1ng c\u00e1c \u0111i\u1ec3m \u1ea3nh.'],['Ch\u00e1y s\u00e1ng (clipping)','V\u00f9ng qu\u00e1 s\u00e1ng m\u1ea5t h\u1ebft chi ti\u1ebft, kh\u00f4ng c\u1ee9u \u0111\u01b0\u1ee3c.'],['D\u1ea3i t\u01b0\u01a1ng ph\u1ea3n \u0111\u1ed9ng','Kho\u1ea3ng ch\u00eanh s\u00e1ng t\u1ed1i c\u1ea3m bi\u1ebfn ghi nh\u1eadn \u0111\u01b0\u1ee3c c\u00f9ng l\u00fac.'],['RAW','\u0110\u1ecbnh d\u1ea1ng l\u01b0u d\u1eef li\u1ec7u g\u1ed1c c\u1ee7a c\u1ea3m bi\u1ebfn, ch\u1ec9nh h\u1eadu k\u1ef3 linh ho\u1ea1t.'],['Tether','Ch\u1ee5p n\u1ed1i m\u00e1y v\u1edbi m\u00e1y t\u00ednh, \u1ea3nh hi\u1ec7n ngay l\u00ean m\u00e0n l\u1edbn.'],['H\u1ec7 s\u1ed1 crop','T\u1ec9 l\u1ec7 c\u1ea3m bi\u1ebfn nh\u1ecf h\u01a1n full-frame, l\u00e0m h\u1eb9p g\u00f3c nh\u00ecn.'],['\u0110\u00e8n pilot (modeling light)','\u0110\u00e8n li\u00ean t\u1ee5c tr\u00ean \u0111\u1ea7u flash \u0111\u1ec3 xem tr\u01b0\u1edbc h\u01b0\u1edbng s\u00e1ng.'],['Speedring','V\u00f2ng g\u00e1 n\u1ed1i softbox v\u00e0o \u0111\u1ea7u \u0111\u00e8n.'],['Ch\u00e2n boom','Ch\u00e2n \u0111\u00e8n c\u00f3 tay v\u01b0\u01a1n ngang \u0111\u1ec3 treo \u0111\u00e8n tr\u00ean \u0111\u1ea7u ch\u1ee7 th\u1ec3.'],['Bao c\u00e1t (sandbag)','T\u00fai n\u1eb7ng \u0111\u00e8 ch\u00e2n \u0111\u00e8n, nh\u1ea5t l\u00e0 ch\u00e2n boom, ch\u1ed1ng \u0111\u1ed5.'],['C-stand','Ch\u00e2n \u0111\u00e8n th\u00e9p ch\u1eafc ch\u1eafn, ch\u00e2n so le, hay d\u00f9ng cho c\u1edd v\u00e0 boom.']];\nfunction initGloss(){const L=$('glList');const q=$('glQ');const norm=s=>s.toLowerCase().normalize('NFD').replace(\/[\\u0300-\\u036f]\/g,'').replace(\/\u0111\/g,'d');\n function draw(){const k=norm(q.value.trim());const rows=GLOSS.filter(g=>!k||norm(g[0]+' '+g[1]).indexOf(k)>=0);L.innerHTML=rows.length?rows.map(g=>'<div class=\"gi\"><b>'+g[0]+'<\/b><span>'+g[1]+'<\/span><\/div>').join(''):'<p class=\"note\">Kh\u00f4ng t\u00ecm th\u1ea5y \u2014 th\u1eed t\u1eeb kh\u00e1c.<\/p>';}\n q.oninput=draw;draw();}\nconst DONE=new Set((()=>{try{return JSON.parse(localStorage.getItem('kblack_lab_done')||'[]');}catch(e){return [];}})());\nfunction saveDone(){try{localStorage.setItem('kblack_lab_done',JSON.stringify([...DONE]));}catch(e){}}\n\nconst LICON={\"expo\": \"<path d=\\\"M12 3 21 19H3z\\\"\/><circle cx=\\\"12\\\" cy=\\\"13.5\\\" r=\\\"2.2\\\"\/>\", \"aperture\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"8.5\\\"\/><path d=\\\"M12 3.5 15 11M20 10l-6.8 4M16.5 19.5 11 14M6 18.5l3.5-6.8M4 9l7 1.5\\\"\/>\", \"shutter\": \"<circle cx=\\\"12\\\" cy=\\\"13\\\" r=\\\"7.5\\\"\/><path d=\\\"M12 13V9M10 3h4M18.5 6.5l-1.3 1.3\\\"\/>\", \"iso\": \"<rect x=\\\"4\\\" y=\\\"4\\\" width=\\\"16\\\" height=\\\"16\\\" rx=\\\"2.5\\\"\/><circle cx=\\\"8.5\\\" cy=\\\"9\\\" r=\\\".9\\\"\/><circle cx=\\\"14\\\" cy=\\\"8\\\" r=\\\".9\\\"\/><circle cx=\\\"11\\\" cy=\\\"12.5\\\" r=\\\".9\\\"\/><circle cx=\\\"16\\\" cy=\\\"13.5\\\" r=\\\".9\\\"\/><circle cx=\\\"8\\\" cy=\\\"15.5\\\" r=\\\".9\\\"\/><circle cx=\\\"13\\\" cy=\\\"17\\\" r=\\\".9\\\"\/>\", \"modes\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"8.5\\\"\/><path d=\\\"M9 15V9l3 3.5L15 9v6\\\"\/>\", \"meter\": \"<path d=\\\"M4 20V14M8.5 20V9M13 20V12M17.5 20V6M3 20h18\\\"\/>\", \"focus\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"3\\\"\/><path d=\\\"M4 8V4h4M20 8V4h-4M4 16v4h4M20 16v4h-4\\\"\/>\", \"focal\": \"<path d=\\\"M3 12h3M18 12h3\\\"\/><path d=\\\"M6 7l12 5-12 5z\\\"\/>\", \"lens\": \"<rect x=\\\"5\\\" y=\\\"7\\\" width=\\\"10\\\" height=\\\"10\\\" rx=\\\"1.5\\\"\/><path d=\\\"M15 9h3.5v6H15M8 7V5M12 7V5\\\"\/>\", \"compo\": \"<rect x=\\\"3.5\\\" y=\\\"5\\\" width=\\\"17\\\" height=\\\"14\\\" rx=\\\"1.5\\\"\/><path d=\\\"M9.2 5v14M14.8 5v14M3.5 9.7h17M3.5 14.3h17\\\"\/>\", \"posing\": \"<circle cx=\\\"12\\\" cy=\\\"5.5\\\" r=\\\"2.3\\\"\/><path d=\\\"M12 8v6.5M12 14.5l-3.5 5.5M12 14.5l3.5 5.5M7 10.5l5-1.5 5 1.5\\\"\/>\", \"light\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"4\\\"\/><path d=\\\"M12 8a4 4 0 0 1 0 8z\\\" fill=\\\"currentColor\\\"\/><path d=\\\"M12 2.5v2.5M12 19v2.5M2.5 12H5M19 12h2.5M5.3 5.3l1.8 1.8M16.9 16.9l1.8 1.8M5.3 18.7l1.8-1.8M16.9 7.1l1.8-1.8\\\"\/>\", \"natlight\": \"<path d=\\\"M3 18h18\\\"\/><path d=\\\"M6.5 18a5.5 5.5 0 0 1 11 0\\\"\/><path d=\\\"M12 6.5v2M5.5 9.5l1.4 1.4M18.5 9.5l-1.4 1.4\\\"\/>\", \"wb\": \"<path d=\\\"M10 4a2 2 0 0 1 4 0v9.5a4 4 0 1 1-4 0z\\\"\/><path d=\\\"M12 11v5\\\"\/>\", \"setups\": \"<path d=\\\"M7 4h6l-1.5 5h-3z\\\"\/><path d=\\\"M10 9v11M6 20h8M16 7l4-2M16 10h4.5\\\"\/>\", \"workflow\": \"<rect x=\\\"4\\\" y=\\\"5\\\" width=\\\"16\\\" height=\\\"11\\\" rx=\\\"1.5\\\"\/><path d=\\\"M2.5 19h19M9 10l2 2 4-4\\\"\/>\", \"session\": \"<rect x=\\\"5\\\" y=\\\"3.5\\\" width=\\\"14\\\" height=\\\"17\\\" rx=\\\"2\\\"\/><path d=\\\"M8.5 9l1.5 1.5L13 7.5M8.5 15h7\\\"\/>\", \"fix\": \"<path d=\\\"M12 4 21 19H3z\\\"\/><path d=\\\"M12 10v4M12 16.5v.5\\\"\/>\", \"glossary\": \"<path d=\\\"M5 4.5h10a3 3 0 0 1 3 3V20H8a3 3 0 0 1-3-3z\\\"\/><path d=\\\"M5 17a3 3 0 0 1 3-3h10\\\"\/>\", \"quiz\": \"<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"8.5\\\"\/><path d=\\\"M9.5 9.5a2.5 2.5 0 1 1 3.5 2.3c-.7.3-1 .8-1 1.5v.4M12 16.5v.5\\\"\/>\"};\nfunction licon(id){return '<svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\">'+(LICON[id]||'<circle cx=\"12\" cy=\"12\" r=\"3\"\/>')+'<\/svg>';}\nfunction buildRail(){const L=$('lesList');L.innerHTML='';let ch=-1;LESSONS.forEach((ls,i)=>{if(ls.ch!==ch){ch=ls.ch;L.appendChild(el('div','chh',CHAPTERS[ch]));}const b=el('button','les'+(i===CURL?' on':''),'<span class=\"ic\">'+licon(ls.id)+'<\/span><span>'+ls.t+'<\/span>'+(DONE.has(ls.id)?'<span class=\"dn\">\u2713<\/span>':''));b.onclick=()=>openLesson(i);L.appendChild(b);});\n const n=LESSONS.filter(l=>DONE.has(l.id)).length;$('progTxt').textContent=n+'\/'+LESSONS.length+' b\u00e0i \u0111\u00e3 h\u1ecdc';$('progBar').style.width=(n\/LESSONS.length*100)+'%';}\nfunction openLesson(i){CURL=i;const ls=LESSONS[i];const W=$('lWrap');W.innerHTML='<div class=\"crumb\">'+CHAPTERS[ls.ch]+' \u00b7 B\u00e0i '+(i+1)+'\/'+LESSONS.length+'<\/div>'+ls.html;\n renderFigures(W);if(ls.ex){W.appendChild(el('div','exbox','<h3>B\u00e0i t\u1eadp th\u1ef1c h\u00e0nh<\/h3><p>'+ls.ex+'<\/p>'));}\n const nav=el('div','lnav');const left=el('div','lnl');if(i>0){const pv=el('button','gbtn','\u2190 '+LESSONS[i-1].t);pv.onclick=()=>openLesson(i-1);left.appendChild(pv);}\n const done=el('button','gbtn',DONE.has(ls.id)?'\u2713 \u0110\u00e3 h\u1ecdc':'\u0110\u00e1nh d\u1ea5u \u0111\u00e3 h\u1ecdc');done.onclick=()=>{if(DONE.has(ls.id))DONE.delete(ls.id);else{DONE.add(ls.id);awardLesson(ls);}saveDone();done.textContent=DONE.has(ls.id)?'\u2713 \u0110\u00e3 h\u1ecdc':'\u0110\u00e1nh d\u1ea5u \u0111\u00e3 h\u1ecdc';buildRail();};left.appendChild(done);nav.appendChild(left);\n if(i<LESSONS.length-1){const nx=el('button','pbtn','B\u00e0i ti\u1ebfp: '+LESSONS[i+1].t);nx.onclick=()=>{DONE.add(ls.id);saveDone();awardLesson(ls);openLesson(i+1);};nav.appendChild(nx);}\n W.appendChild(nav);if(ls.init)ls.init();buildRail();$('lBody').scrollTop=0;const mt=$('mLesTxt');if(mt)mt.textContent='B\u00e0i '+(i+1)+'\/'+LESSONS.length+' \u00b7 '+ls.t;$('rail').classList.remove('open');document.body.classList.remove('noscroll');if(window.innerWidth<=760)window.scrollTo(0,0);}\n\/* --- exposure simulator --- *\/\n\/* --- focal length --- *\/\nfunction initFocal(){const cv=$('focCv');const ctx=ctx2d(cv);const F=[14,24,35,50,85,135,200];const S={fi:4};\n $('focCtl').appendChild(sld('Ti\u00eau c\u1ef1',0,F.length-1,1,S.fi,v=>F[v]+'mm',v=>{S.fi=v;draw();},1));\n const use={14:'N\u1ed9i th\u1ea5t, ki\u1ebfn tr\u00fac, phong c\u1ea3nh r\u1ed9ng',24:'Phong c\u1ea3nh, kh\u00f4ng gian, \u1ea3nh nh\u00f3m \u0111\u00f4ng',35:'\u0110\u01b0\u1eddng ph\u1ed1, ph\u00f3ng s\u1ef1, k\u1ec3 chuy\u1ec7n',50:'\u0110a d\u1ee5ng, g\u1ea7n m\u1eaft ng\u01b0\u1eddi',85:'Ch\u00e2n dung kinh \u0111i\u1ec3n, profile',135:'Ch\u00e2n dung n\u00e9n ph\u00f4ng, s\u00e2n kh\u1ea5u',200:'Th\u1ec3 thao, s\u1ef1 ki\u1ec7n xa, n\u00e9n c\u1ef1c m\u1ea1nh'};\n $('focCtl').appendChild(el('div','note','<span id=\"focUse\"><\/span>'));\n const T=$('focTbl');T.innerHTML='<tr><th>Ti\u00eau c\u1ef1<\/th><th>C\u1eadn m\u1eb7t<\/th><th>N\u1eeda ng\u01b0\u1eddi<\/th><th>To\u00e0n th\u00e2n<\/th><\/tr>'+[35,50,85,105,135].map(f=>'<tr><td>'+f+'mm<\/td><td>'+(f*0.45\/36).toFixed(1)+' m<\/td><td>'+(f*0.95\/36).toFixed(1)+' m<\/td><td>'+(f*1.95\/36).toFixed(1)+' m<\/td><\/tr>').join('');\n const pano=document.createElement('canvas');pano.width=2400;pano.height=600;const p=ctx2d(pano);\n if(p){const g=p.createLinearGradient(0,0,0,600);g.addColorStop(0,'#1d3a66');g.addColorStop(.6,'#e9a86b');g.addColorStop(1,'#2a2320');p.fillStyle=g;p.fillRect(0,0,2400,600);\n  for(let i=0;i<40;i++){const w=40+((i*37)%70),h=80+((i*53)%190);p.fillStyle=i%2?'#1c2232':'#242b3d';p.fillRect(i*62-20,430-h,w,h);}\n  p.fillStyle='#2a2320';p.fillRect(0,430,2400,170);\n  for(let i=0;i<9;i++){const x=300+i*230;if(Math.abs(x-1200)<120)continue;p.fillStyle='#3a3f4f';p.beginPath();p.arc(x,452,12,0,7);p.fill();p.fillRect(x-10,462,20,50);}\n  p.fillStyle='#e8e2d8';p.beginPath();p.arc(1200,400,22,0,7);p.fill();p.fillStyle='#2f6bff';p.fillRect(1180,424,40,90);}\n function draw(){const f=F[S.fi];const hf=2*Math.atan(18\/f);$('focUse').textContent=use[f];\n  if(ctx){ctx.fillStyle='#0d1322';ctx.fillRect(0,0,960,400);\n   const cx=180,cy=360;ctx.fillStyle='#18223a';ctx.fillRect(20,20,320,360);ctx.strokeStyle='#ffb259';ctx.fillStyle='rgba(255,178,89,.13)';ctx.beginPath();ctx.moveTo(cx,cy);const L=330;ctx.lineTo(cx-Math.tan(hf\/2)*L,cy-L);ctx.lineTo(cx+Math.tan(hf\/2)*L,cy-L);ctx.closePath();ctx.fill();ctx.stroke();\n   ctx.fillStyle='#fff';ctx.beginPath();ctx.moveTo(cx,cy-8);ctx.lineTo(cx-10,cy+8);ctx.lineTo(cx+10,cy+8);ctx.fill();\n   ctx.fillStyle='#8e9ab3';ctx.font='600 18px \"Be Vietnam Pro\"';ctx.fillText(Math.round(hf*180\/Math.PI)+'\u00b0 ngang',cx-40,50);\n   const vis=clamp(2400*14\/f\/1.28*0.6,120,2400);const fw=560,fh=373,fx=370,fy=14;ctx.drawImage(pano,1200-vis\/2,300-vis\/3,vis,vis*2\/3,fx,fy,fw,fh);ctx.strokeStyle='#fff';ctx.strokeRect(fx,fy,fw,fh);}\n  $('focRead').innerHTML='G\u00f3c nh\u00ecn ngang <b>'+Math.round(hf*180\/Math.PI)+'\u00b0<\/b> &nbsp; To\u00e0n th\u00e2n d\u1ecdc c\u1ea7n l\u00f9i <b>'+(f*1.95\/36).toFixed(1)+' m<\/b>';}\n draw();}\n\n\/* --- composition --- *\/\n\/* --- light hardness & inverse square --- *\/\nfunction initLight(){const cv=$('ltCv');const ctx=ctx2d(cv);const S={d:1.5,s:0.9};\n $('ltCtl').appendChild(sld('Kho\u1ea3ng c\u00e1ch \u0111\u00e8n',0.5,4,0.1,S.d,v=>v.toFixed(1)+' m',v=>{S.d=v;draw();}));\n $('ltCtl').appendChild(sld('K\u00edch th\u01b0\u1edbc ngu\u1ed3n s\u00e1ng',0.1,1.8,0.05,S.s,v=>Math.round(v*100)+' cm',v=>{S.s=v;draw();}));\n function draw(){const rel=1\/(S.d*S.d);const stops=Math.log2(rel\/(1\/(1.5*1.5)));const soft=S.s\/S.d;\n  if(ctx){ctx.fillStyle='#0d1322';ctx.fillRect(0,0,960,420);\n   ctx.strokeStyle='#243150';ctx.beginPath();ctx.moveTo(60,360);ctx.lineTo(460,360);ctx.moveTo(60,40);ctx.lineTo(60,360);ctx.stroke();\n   ctx.strokeStyle='#ffb259';ctx.lineWidth=3;ctx.beginPath();for(let x=0;x<=400;x++){const d=0.5+x\/400*3.5;const y=360-(1\/(d*d))\/4*320;x?ctx.lineTo(60+x,y):ctx.moveTo(60+x,y);}ctx.stroke();ctx.lineWidth=1;\n   const mx=60+(S.d-0.5)\/3.5*400,my=360-rel\/4*320;ctx.fillStyle='#fff';ctx.beginPath();ctx.arc(mx,my,7,0,7);ctx.fill();\n   ctx.fillStyle='#8e9ab3';ctx.font='600 16px \"Be Vietnam Pro\"';ctx.fillText('\u0111\u1ed9 s\u00e1ng',66,34);ctx.fillText('kho\u1ea3ng c\u00e1ch (m)',340,390);\n   const cx=720,cy=210;const blur=clamp(soft*26,1,60);ctx.save();ctx.filter='blur('+blur.toFixed(1)+'px)';ctx.fillStyle='rgba(0,0,0,.85)';ctx.beginPath();ctx.ellipse(cx+70,cy+130,95,26,0,0,7);ctx.fill();ctx.restore();\n   const g=ctx.createRadialGradient(cx-40,cy-40,10,cx,cy,110);const hard=clamp(1-soft,0,1);g.addColorStop(0,'#f5f1ea');g.addColorStop(0.35+0.4*(1-hard)*0.5,'#bdb6ad');g.addColorStop(1,'#26221f');ctx.fillStyle=g;ctx.beginPath();ctx.arc(cx,cy,100,0,7);ctx.fill();}\n  $('ltRead').innerHTML='\u0110\u1ed9 s\u00e1ng so v\u1edbi 1,5 m <b>'+(stops>=0?'+':'')+stops.toFixed(1)+' stop<\/b> &nbsp; \u0110\u1ed9 m\u1ec1m <b>'+(soft>0.8?'r\u1ea5t m\u1ec1m':soft>0.45?'m\u1ec1m':soft>0.2?'trung t\u00ednh':'c\u1ee9ng')+'<\/b>';}\n draw();}\n\n\/* --- white balance --- *\/\nfunction initWB(){const S={k:3200,wb:5600};\n $('wbCtl').appendChild(sld('Ngu\u1ed3n s\u00e1ng',2500,9000,100,S.k,v=>v+'K',v=>{S.k=v;draw();}));\n $('wbCtl').appendChild(sld('C\u00e2n b\u1eb1ng tr\u1eafng tr\u00ean m\u00e1y',2500,9000,100,S.wb,v=>v+'K',v=>{S.wb=v;draw();}));\n function draw(){const c=wbColor(S.k,S.wb);const base=[[0.94,0.94,0.94,'Gi\u1ea5y tr\u1eafng'],[0.86,0.66,0.55,'L\u00e0n da'],[0.5,0.5,0.52,'\u00c1o x\u00e1m']];\n  $('wbSw').innerHTML=base.map(b=>'<div class=\"sw\" style=\"background:'+rgbCss([b[0]*c[0],b[1]*c[1],b[2]*c[2]])+'\">'+b[3]+'<\/div>').join('');\n  const d=S.k-S.wb;const v=$('wbVer');if(Math.abs(d)<300){v.className='verdict ok';v.textContent='Tr\u1eafng chu\u1ea9n \u2014 WB kh\u1edbp ngu\u1ed3n s\u00e1ng';}else if(d<0){v.className='verdict over';v.textContent='\u1ea2nh \u00e1m cam \u2014 h\u1ea1 WB xu\u1ed1ng g\u1ea7n '+S.k+'K';}else{v.className='verdict under';v.textContent='\u1ea2nh \u00e1m xanh \u2014 n\u00e2ng WB l\u00ean g\u1ea7n '+S.k+'K';}}\n draw();}\n\n\/* --- setups cards --- *\/\nconst SETUP_TXT={rembrandt:['Rembrandt','\u0110\u00e8n ch\u00ednh 45\u00b0 v\u00e0 cao h\u01a1n m\u1eaft. M\u00e1 ph\u00eda t\u1ed1i c\u00f3 m\u1ed9t tam gi\u00e1c s\u00e1ng nh\u1ecf d\u01b0\u1edbi m\u1eaft. K\u1ecbch t\u00ednh, c\u00f3 chi\u1ec1u s\u00e2u \u2014 h\u1ee3p ch\u00e2n dung doanh nh\u00e2n, ngh\u1ec7 thu\u1eadt.'],\n loop:['Loop','\u0110\u00e8n l\u1ec7ch 30\u00b0. B\u00f3ng m\u0169i t\u1ea1o m\u1ed9t v\u00f2ng nh\u1ecf xu\u1ed1ng m\u00e1, ch\u01b0a ch\u1ea1m b\u00f3ng m\u00e1. D\u1ec5 ch\u1ee5p, h\u1ee3p nhi\u1ec1u khu\u00f4n m\u1eb7t \u2014 l\u1ef1a ch\u1ecdn an to\u00e0n cho profile.'],\n butterfly:['Butterfly','\u0110\u00e8n ch\u00ednh ngay tr\u01b0\u1edbc m\u1eb7t, cao. B\u00f3ng h\u00ecnh c\u00e1nh b\u01b0\u1edbm d\u01b0\u1edbi m\u0169i, g\u00f2 m\u00e1 n\u1ed5i. Chu\u1ea9n \u1ea3nh beauty, ng\u01b0\u1eddi m\u1eabu.'],\n split:['Split','\u0110\u00e8n 90\u00b0 t\u1eeb m\u1ed9t b\u00ean. N\u1eeda m\u1eb7t s\u00e1ng, n\u1eeda m\u1eb7t t\u1ed1i. B\u00ed \u1ea9n, c\u00e1 t\u00ednh m\u1ea1nh.'],\n clamshell:['Clamshell','Hai \u0111\u00e8n k\u1eb9p tr\u00ean \u2013 d\u01b0\u1edbi m\u1eb7t nh\u01b0 v\u1ecf s\u00f2. Da m\u1ecbn, g\u1ea7n nh\u01b0 kh\u00f4ng b\u00f3ng. Beauty, m\u1ef9 ph\u1ea9m, spa.'],\n three:['Ba \u0111i\u1ec3m + t\u00f3c + n\u1ec1n','Key, Fill, Rim sau l\u01b0ng t\u00e1ch vai, \u0111\u00e8n t\u00f3c treo boom tr\u00ean \u0111\u1ea7u, \u0111\u00e8n n\u1ec1n chi\u1ebfu ph\u00f4ng. N\u1ec1n t\u1ea3ng c\u1ee7a ph\u1ecfng v\u1ea5n, phim doanh nghi\u1ec7p.'],\n boom:['\u0110\u00e8n \u0111\u1ec9nh boom','Octabox treo tr\u00ean \u0111\u1ea7u b\u1eb1ng ch\u00e2n boom, chi\u1ebfu th\u1eb3ng xu\u1ed1ng. H\u1ed1c m\u1eaft s\u00e2u, kh\u1ed1i m\u1eb7t m\u1ea1nh \u2014 ki\u1ec3u \u1ea3nh \u0111i\u1ec7n \u1ea3nh, t\u1ea1p ch\u00ed.'],\n highkey:['High-key','N\u1ec1n tr\u1eafng tinh, s\u00e1ng \u0111\u1ec1u, \u00edt b\u00f3ng. Hai \u0111\u00e8n b\u1eafn ph\u00f4ng. \u1ea2nh th\u01b0\u01a1ng m\u1ea1i, e-commerce, \u1ea3nh th\u1ebb cao c\u1ea5p.'],\n lowkey:['Low-key','N\u1ec1n \u0111en, stripbox g\u1eafn t\u1ed5 ong khoanh v\u00f9ng s\u00e1ng, rim sau l\u01b0ng. M\u1ea1nh, sang, \u0111i\u1ec7n \u1ea3nh \u2014 \u0111\u00fang ch\u1ea5t K-BLACK.'],\n group:['Ch\u1ee5p nh\u00f3m \u0111\u00f4ng ng\u01b0\u1eddi','Hai d\u00f9 l\u1edbn \u0111\u1eb7t xa, ch\u00e9o 35\u00b0 hai b\u00ean m\u00e1y, n\u00e2ng cao \u0111\u1ec3 ng\u01b0\u1eddi tr\u01b0\u1edbc kh\u00f4ng \u0111\u1ed5 b\u00f3ng l\u00ean ng\u01b0\u1eddi sau. M\u00e1y \u0111o s\u00e1ng b\u00e1o \u0111\u1ed9 ch\u00eanh gi\u1eefa ng\u01b0\u1eddi \u0111\u1ee9ng gi\u1eefa v\u00e0 \u0111\u1ee9ng r\u00eca.'],\n colorbg:['Ph\u00f4ng loang m\u00e0u','Ph\u00f4ng x\u00e1m, hai \u0111\u00e8n g\u1eafn gel xanh v\u00e0 h\u1ed3ng c\u00f3 t\u1ed5 ong r\u1ecdi hai v\u00f9ng kh\u00e1c nhau tr\u00ean ph\u00f4ng \u2014 t\u1ea1o m\u1ea3ng m\u00e0u loang. \u0110\u00e8n ch\u00ednh gi\u1eef da \u0111\u00fang m\u00e0u.'],\n product:['S\u1ea3n ph\u1ea9m','Softbox l\u1edbn \u0111\u1eb7t ngang cho d\u1ea3i s\u00e1ng d\u00e0i tr\u00ean chai, \u0111\u00e8n \u0111\u1ec9nh t\u00e1ch n\u1eafp. Chu\u1ea9n ch\u1ee5p m\u1ef9 ph\u1ea9m, \u0111\u1ed3 u\u1ed1ng.']};\n\/* --- quiz --- *\/\nconst QUIZ=[\n ['Mu\u1ed1n ph\u00f4ng n\u1ec1n m\u1edd nh\u1ea5t, b\u1ea1n ch\u1ecdn kh\u1ea9u n\u00e0o?',['f\/2','f\/8','f\/16'],0,'S\u1ed1 f c\u00e0ng nh\u1ecf, l\u1ed7 kh\u1ea9u c\u00e0ng to, v\u00f9ng n\u00e9t c\u00e0ng m\u1ecfng.'],\n ['\u0110\u1ed5i t\u1eeb 1\/125 sang 1\/250, \u1ea3nh s\u1ebd:',['S\u00e1ng h\u01a1n 1 stop','T\u1ed1i \u0111i 1 stop','Kh\u00f4ng \u0111\u1ed5i'],1,'Th\u1eddi gian ph\u01a1i s\u00e1ng gi\u1ea3m m\u1ed9t n\u1eeda n\u00ean t\u1ed1i \u0111i 1 stop.'],\n ['\u0110\u00e8n \u0111ang c\u00e1ch m\u1eb7t 1 m, l\u00f9i ra 2 m th\u00ec s\u00e1ng c\u00f2n:',['1\/2','1\/4','1\/8'],1,'Lu\u1eadt b\u00ecnh ph\u01b0\u01a1ng ngh\u1ecbch \u0111\u1ea3o: g\u1ea5p \u0111\u00f4i kho\u1ea3ng c\u00e1ch c\u00f2n 1\/4 (\u22122 stop).'],\n ['C\u00e1ch l\u00e0m \u00e1nh s\u00e1ng m\u1ec1m h\u01a1n hi\u1ec7u qu\u1ea3 nh\u1ea5t:',['T\u0103ng c\u00f4ng su\u1ea5t \u0111\u00e8n','D\u00f9ng softbox to v\u00e0 \u0111\u1eb7t g\u1ea7n','L\u00f9i \u0111\u00e8n th\u1eadt xa'],1,'\u0110\u1ed9 m\u1ec1m ph\u1ee5 thu\u1ed9c k\u00edch th\u01b0\u1edbc ngu\u1ed3n so v\u1edbi ch\u1ee7 th\u1ec3, kh\u00f4ng ph\u1ee5 thu\u1ed9c c\u00f4ng su\u1ea5t.'],\n ['Ch\u1ee5p d\u01b0\u1edbi \u0111\u00e8n s\u1ee3i \u0111\u1ed1t 3000K nh\u01b0ng \u0111\u1ec3 WB 5600K, \u1ea3nh s\u1ebd:',['\u00c1m cam','\u00c1m xanh','Tr\u1eafng chu\u1ea9n'],0,'WB cao h\u01a1n ngu\u1ed3n s\u00e1ng th\u00ec m\u00e1y kh\u00f4ng tr\u1eeb \u0111\u1ee7 m\u00e0u cam.'],\n ['S\u01a1 \u0111\u1ed3 c\u00f3 tam gi\u00e1c s\u00e1ng nh\u1ecf d\u01b0\u1edbi m\u1eaft ph\u00eda t\u1ed1i l\u00e0:',['Butterfly','Rembrandt','Split'],1,'Rembrandt: \u0111\u00e8n 45\u00b0 v\u00e0 cao, t\u1ea1o tam gi\u00e1c s\u00e1ng tr\u00ean m\u00e1 ph\u00eda t\u1ed1i.'],\n ['Ch\u1ee5p flash, t\u0103ng t\u1ed1c t\u1eeb 1\/60 l\u00ean 1\/200 th\u00ec:',['Ch\u1ee7 th\u1ec3 t\u1ed1i \u0111i g\u1ea7n 2 stop','Ch\u1ee7 th\u1ec3 g\u1ea7n nh\u01b0 kh\u00f4ng \u0111\u1ed5i, s\u00e1ng m\u00f4i tr\u01b0\u1eddng t\u1ed1i \u0111i','\u1ea2nh nho\u00e8 h\u01a1n'],1,'Tia flash r\u1ea5t ng\u1eafn n\u00ean t\u1ed1c ch\u1ee7 y\u1ebfu \u0111i\u1ec1u khi\u1ec3n \u00e1nh s\u00e1ng m\u00f4i tr\u01b0\u1eddng.'],\n ['Ch\u1ee5p to\u00e0n th\u00e2n khung d\u1ecdc b\u1eb1ng \u1ed1ng 85mm c\u1ea7n l\u00f9i kho\u1ea3ng:',['2 m','4,6 m','8 m'],1,'Chi\u1ec1u cao ~1,95 m \u1ee9ng v\u1edbi c\u1ea1nh 36mm: 85 \u00d7 1,95 \/ 36 \u2248 4,6 m.'],\n ['Studio d\u00f9ng flash c\u1ed1 \u0111\u1ecbnh, ch\u1ebf \u0111\u1ed9 ph\u00f9 h\u1ee3p nh\u1ea5t:',['M','A','P'],0,'\u00c1nh s\u00e1ng \u0111\u00e3 kho\u00e1 c\u1ed1 \u0111\u1ecbnh; m\u00e1y \u0111o s\u00e1ng c\u1ee7a m\u00e1y \u1ea3nh kh\u00f4ng th\u1ea5y tia flash.'],\n ['Ch\u1ee5p ng\u01b0\u1eddi tr\u01b0\u1edbc ph\u00f4ng tr\u1eafng b\u1eb1ng ch\u1ebf \u0111\u1ed9 t\u1ef1 \u0111\u1ed9ng, \u1ea3nh th\u01b0\u1eddng:',['Qu\u00e1 s\u00e1ng','X\u00e1m v\u00e0 thi\u1ebfu s\u00e1ng','\u0110\u00fang s\u00e1ng'],1,'M\u00e1y k\u00e9o c\u1ea3nh v\u1ec1 x\u00e1m trung t\u00ednh \u2014 c\u1ea7n b\u00f9 kho\u1ea3ng +1 EV.'],\n ['Histogram d\u1ed3n s\u00e1t m\u00e9p ph\u1ea3i ngh\u0129a l\u00e0:',['Thi\u1ebfu s\u00e1ng','Ch\u00e1y s\u00e1ng v\u00f9ng s\u00e1ng','\u1ea2nh nhi\u1ec1u m\u00e0u'],1,'M\u00e9p ph\u1ea3i l\u00e0 tr\u1eafng tuy\u1ec7t \u0111\u1ed1i \u2014 d\u1eef li\u1ec7u \u0111\u00e3 m\u1ea5t.'],\n ['Ch\u1ee5p ng\u01b0\u1eddi \u0111ang ch\u1ea1y v\u1ec1 ph\u00eda b\u1ea1n, ch\u1ebf \u0111\u1ed9 l\u1ea5y n\u00e9t:',['AF-S','AF-C','L\u1ea5y n\u00e9t tay'],1,'AF-C b\u00e1m n\u00e9t li\u00ean t\u1ee5c khi kho\u1ea3ng c\u00e1ch thay \u0111\u1ed5i.'],\n ['\u0110\u00f3ng kh\u1ea9u t\u1eeb f\/2 xu\u1ed1ng f\/8, v\u00f9ng n\u00e9t:',['M\u1ecfng h\u01a1n','D\u00e0y h\u01a1n','Kh\u00f4ng \u0111\u1ed5i'],1,'Kh\u1ea9u nh\u1ecf (s\u1ed1 f l\u1edbn) cho v\u00f9ng n\u00e9t d\u00e0y h\u01a1n.'],\n ['\u1ed0ng 50mm tr\u00ean m\u00e1y APS-C (crop 1,5) cho g\u00f3c nh\u00ecn nh\u01b0:',['33mm','50mm','75mm'],2,'50 \u00d7 1,5 = 75mm t\u01b0\u01a1ng \u0111\u01b0\u01a1ng full-frame.'],\n ['Kh\u00e1ch c\u00f3 n\u1ecdng c\u1eb1m, c\u00e2u h\u01b0\u1edbng d\u1eabn \u0111\u00fang l\u00e0:',['Ng\u1eeda c\u1eb1m l\u00ean','\u0110\u01b0a c\u1eb1m ra tr\u01b0\u1edbc r\u1ed3i h\u1ea1 nh\u1eb9','R\u1ee5t c\u1ed5 l\u1ea1i'],1,'\u0110\u01b0a c\u1eb1m ra tr\u01b0\u1edbc k\u00e9o c\u0103ng v\u00f9ng d\u01b0\u1edbi c\u1eb1m, \u0111\u01b0\u1eddng h\u00e0m r\u00f5.'],\n ['Gi\u1eefa tr\u01b0a n\u1eafng g\u1eaft, c\u00e1ch nhanh nh\u1ea5t c\u00f3 \u1ea3nh ch\u00e2n dung m\u1ec1m:',['T\u0103ng ISO','\u0110\u01b0a ng\u01b0\u1eddi v\u00e0o b\u00f3ng r\u00e2m m\u1edf','\u0110\u00f3ng kh\u1ea9u f\/16'],1,'B\u00f3ng r\u00e2m m\u1edf cho \u00e1nh s\u00e1ng m\u1ec1m c\u00f3 h\u01b0\u1edbng t\u1eeb b\u1ea7u tr\u1eddi.'],\n ['L\u1ee3i \u00edch l\u1edbn nh\u1ea5t c\u1ee7a ch\u1ee5p tether trong studio:',['File nh\u1ecf h\u01a1n','Kh\u00e1ch v\u00e0 ekip th\u1ea5y \u1ea3nh ngay tr\u00ean m\u00e0n l\u1edbn','Pin l\u00e2u h\u01a1n'],1,'Ph\u00e1t hi\u1ec7n l\u1ed7i v\u00e0 duy\u1ec7t m\u00e0u ngay khi c\u00f2n s\u1eeda \u0111\u01b0\u1ee3c.'],\n ['B\u00f3ng ng\u01b0\u1eddi in l\u00ean ph\u00f4ng, c\u00e1ch s\u1eeda:',['T\u0103ng c\u00f4ng su\u1ea5t','K\u00e9o ng\u01b0\u1eddi ra xa ph\u00f4ng, n\u00e2ng \u0111\u00e8n','\u0110\u1ed5i sang ISO th\u1ea5p'],1,'Kho\u1ea3ng c\u00e1ch ng\u01b0\u1eddi\u2013ph\u00f4ng l\u1edbn v\u00e0 \u0111\u00e8n cao s\u1ebd \u0111\u1ea9y b\u00f3ng xu\u1ed1ng s\u00e0n, ra kh\u1ecfi khung.'],\n ['\u0110\u00e8n rim \u0111\u1eb7t \u1edf \u0111\u00e2u?',['C\u1ea1nh m\u00e1y \u1ea3nh','Sau l\u01b0ng ch\u1ee7 th\u1ec3, ch\u1ebfch 120\u2013170\u00b0','Ngay d\u01b0\u1edbi c\u1eb1m'],1,'Rim chi\u1ebfu t\u1eeb sau l\u01b0ng \u0111\u1ec3 t\u1ea1o \u0111\u01b0\u1eddng vi\u1ec1n s\u00e1ng tr\u00ean vai v\u00e0 t\u00f3c.'],\n ['M\u1eaft k\u00ednh b\u1ecb lo\u00e1 \u0111\u00e8n, c\u00e1ch s\u1eeda:',['H\u1ea1 \u0111\u00e8n ngang t\u1ea7m m\u1eaft','N\u00e2ng \u0111\u00e8n ho\u1eb7c \u0111\u01b0a \u0111\u00e8n sang b\u00ean th\u00eam 15\u201320\u00b0','T\u0103ng t\u1ed1c m\u00e0n tr\u1eadp'],1,'\u0110\u01b0a \u0111\u00e8n ra kh\u1ecfi g\u00f3c ph\u1ea3n x\u1ea1 c\u1ee7a m\u1eb7t k\u00ednh.']];\nfunction initQuiz(){const B=$('quizBox');B.innerHTML='';$('quizScore').style.display='none';const pool=QUIZ.map((q,i)=>i).sort(()=>Math.random()-.5).slice(0,10);let right=0,answered=0;\n pool.forEach((qi,n)=>{const q=QUIZ[qi];const box=el('div','qz','<h3>'+(n+1)+'. '+q[0]+'<\/h3>');const ex=el('div','ex',q[3]);q[1].forEach((o,oi)=>{const b=el('button','opt',o);b.onclick=()=>{if(box.dataset.done)return;box.dataset.done=1;answered++;if(oi===q[2]){b.classList.add('right');right++;}else{b.classList.add('wrong');box.querySelectorAll('.opt')[q[2]].classList.add('right');}ex.style.display='block';\n  if(answered===pool.length){addXP(right*10,'Ki\u1ec3m tra nhanh: '+right+'\/'+pool.length);if(right>GAME.quizBest){GAME.quizBest=right;saveGame();}const s=$('quizScore');s.style.display='block';s.innerHTML='B\u1ea1n \u0111\u00fang '+right+'\/'+pool.length+' c\u00e2u'+(right===pool.length?' \u2014 xu\u1ea5t s\u1eafc!':right>=7?' \u2014 n\u1eafm kh\u00e1 ch\u1eafc r\u1ed3i.':' \u2014 xem l\u1ea1i c\u00e1c b\u00e0i li\u00ean quan nh\u00e9.')+' <button class=\"gbtn\" id=\"quizAgain\" style=\"margin-left:10px\">L\u00e0m b\u1ed9 c\u00e2u kh\u00e1c<\/button>';$('quizAgain').onclick=initQuiz;}};box.appendChild(b);});box.appendChild(ex);B.appendChild(box);});}\n\/* =====================================================================\n   TAB 2 \u2014 STUDIO 3D\n   ===================================================================== *\/\nconst V=(x,y,z)=>({x,y,z});const vsub=(a,b)=>V(a.x-b.x,a.y-b.y,a.z-b.z);const vlen=a=>Math.hypot(a.x,a.y,a.z);const vdot=(a,b)=>a.x*b.x+a.y*b.y+a.z*b.z;const vscl=(a,s)=>V(a.x*s,a.y*s,a.z*s);const vnrm=a=>{const l=vlen(a)||1;return vscl(a,1\/l);};const vadd=(a,b)=>V(a.x+b.x,a.y+b.y,a.z+b.z);\nfunction smooth(e0,e1,x){if(e1<=e0)return x>=e0?1:0;const t=clamp((x-e0)\/(e1-e0),0,1);return t*t*(3-2*t);}\nconst MODS={\n softbox:{n:'Softbox ch\u1eef nh\u1eadt',shape:'rect',sizes:[[0.6,0.9,'60\u00d790'],[0.8,1.2,'80\u00d7120'],[0.9,0.9,'90\u00d790'],[1.2,1.8,'120\u00d7180']],eff:0.5,spread:75,area:true},\n octa:{n:'Octabox',shape:'oct',sizes:[[0.9,0.9,'\u00d890'],[1.2,1.2,'\u00d8120'],[1.5,1.5,'\u00d8150']],eff:0.5,spread:75,area:true},\n strip:{n:'Stripbox',shape:'rect',sizes:[[0.3,1.2,'30\u00d7120'],[0.35,1.6,'35\u00d7160'],[0.4,1.8,'40\u00d7180']],eff:0.45,spread:70,area:true},\n para:{n:'Parabolic',shape:'oct',sizes:[[0.7,0.7,'\u00d870'],[0.9,0.9,'\u00d890'],[1.2,1.2,'\u00d8120']],eff:0.65,spread:60,area:true},\n dish:{n:'Beauty dish',shape:'disc',sizes:[[0.42,0.42,'\u00d842'],[0.55,0.55,'\u00d855'],[0.7,0.7,'\u00d870']],eff:0.7,spread:60,area:true},\n umb:{n:'D\u00f9 xuy\u00ean s\u00e1ng',shape:'disc',sizes:[[1.0,1.0,'\u00d8100'],[1.5,1.5,'\u00d8150']],eff:0.4,spread:100,area:true},\n bare:{n:'Ch\u00f3a ti\u00eau chu\u1ea9n',shape:'cone',sizes:[[0.18,0.18,'\u00d818']],eff:0.9,spread:55,area:false},\n fresnel:{n:'Fresnel \/ spot',shape:'cone',sizes:[[0.2,0.2,'\u00d820']],eff:1.1,spread:30,area:false}};\nconst WALLS={white:{n:'Tr\u1eafng',c:'#e8e6e1',r:.8},grey:{n:'X\u00e1m',c:'#86898e',r:.35},black:{n:'\u0110en',c:'#18181a',r:.05},brick:{n:'G\u1ea1ch m\u1ed9c',c:'#8a4a32',r:.22}};\nconst BDCOL=[['#eeeeee','Tr\u1eafng'],['#d9d9d6','X\u00e1m nh\u1ea1t'],['#8e9196','X\u00e1m'],['#4a4d52','X\u00e1m than'],['#141416','\u0110en'],['#e9dcc6','Kem'],['#b58d62','Kraft'],['#5a3b2a','N\u00e2u socola'],['#6e1f2a','\u0110\u1ecf \u0111\u00f4'],['#f2c6cf','H\u1ed3ng pastel'],['#e0a33a','V\u00e0ng m\u00f9 t\u1ea1t'],['#c8612f','Cam \u0111\u1ea5t'],['#9bd3c0','Xanh mint'],['#56705a','Xanh olive'],['#1d2b4f','Navy'],['#2c5aa0','Xanh d\u01b0\u01a1ng'],['#5b3f8f','T\u00edm'],['#2f8f3f','Xanh chroma'],['#1f4fbf','Blue screen']];\nconst LCOLS=['#ffb259','#7aa2ff','#ff7a9c','#5ee0a0','#c89bff'];\nconst FOC=[24,35,50,85,105,135,200];\nconst SAP=[1.4,1.8,2,2.8,3.5,4,5.6,8,11,16,22];\nconst SSH=[1\/4000,1\/2000,1\/1000,1\/500,1\/250,1\/200,1\/160,1\/125,1\/100,1\/60,1\/30,1\/15,1\/8];\nconst SIS=[100,200,400,800,1600,3200,6400];\nlet _lid=0;const lid=()=>'L'+Date.now().toString(36)+(_lid++);\nconst ROLES={key:{n:'Key \u2014 \u0111\u00e8n ch\u00ednh',o:{mod:'octa',size:1,power:300,az:40,dist:1.6,height:2.1,aim:'face',grid:false,boom:false}},\n fill:{n:'Fill \u2014 \u0111\u00e8n b\u00f9',o:{mod:'softbox',size:0,power:80,az:-40,dist:2.5,height:1.6,aim:'face',grid:false,boom:false}},\n rim:{n:'Rim \u2014 \u0111\u00e8n vi\u1ec1n sau l\u01b0ng',o:{mod:'strip',size:0,power:200,az:145,dist:1.5,height:2.0,aim:'hair',grid:true,boom:false}},\n kicker:{n:'Kicker \u2014 vi\u1ec1n h\u00f4ng sau',o:{mod:'strip',size:0,power:150,az:-120,dist:1.6,height:1.7,aim:'face',grid:true,boom:false}},\n hair:{n:'T\u00f3c \u2014 boom sau \u0111\u1ea7u',o:{mod:'strip',size:0,power:120,az:170,dist:0.55,height:2.45,aim:'hair',grid:true,boom:true}},\n top:{n:'\u0110\u1ec9nh \u2014 boom tr\u00ean \u0111\u1ea7u',o:{mod:'octa',size:0,power:220,az:0,dist:0.35,height:2.55,aim:'face',grid:false,boom:true}},\n bg:{n:'N\u1ec1n \u2014 chi\u1ebfu ph\u00f4ng',o:{mod:'bare',size:0,power:150,az:180,dist:0.9,height:0.9,aim:'bg',grid:false,boom:false}}};\nconst ROLE_NAME={key:'Key',fill:'Fill',rim:'Rim',kicker:'Kicker',hair:'T\u00f3c',top:'\u0110\u1ec9nh',bg:'N\u1ec1n'};\nfunction roleShort(k){return ROLES[k]?ROLES[k].n.split(' \u2014 ')[0]:'';}\nfunction mkLight(o){return Object.assign({id:lid(),name:'Key',role:'key',on:true,kind:'led',power:300,mod:'octa',size:1,grid:false,kelvin:5600,az:45,dist:1.6,height:2.1,aim:'face',boom:false,gel:'',bgX:null,bgY:null},o||{});}\nfunction guessRole(L){const n=(L.name||'').toLowerCase();if(n.indexOf('rim')>=0||n.indexOf('vi\u1ec1n')>=0)return 'rim';if(n.indexOf('fill')>=0)return 'fill';if(n.indexOf('n\u1ec1n')>=0)return 'bg';if(n.indexOf('t\u00f3c')>=0)return 'hair';if(n.indexOf('top')>=0||n.indexOf('\u0111\u1ec9nh')>=0)return 'top';return 'key';}\nfunction migrateST(s){s.subj.count=s.subj.count||10;if(s.subj.rot==null)s.subj.rot=0;if(!s.subj.char)s.subj.char='b_office';s.cam.az=s.cam.az||0;s.cam.tilt=s.cam.tilt||0;s.cam.pan=s.cam.pan||0;if(!s.cam.aspect)s.cam.aspect=s.cam.portrait===false?'3:2':'2:3';s.bd.x=s.bd.x||0;s.bd.floor=s.bd.floor||2.2;s.bd.w=s.bd.w||2.72;if(s.bd.tex==null)s.bd.tex=false;s.view=Object.assign({dims:true,marks:true,tags:true},s.view||{});s.lights.forEach(L=>{if(L.boom==null)L.boom=false;if(!L.role)L.role=guessRole(L);});return s;}\nfunction defaultST(){return migrateST({room:{w:6,l:6.5,h:4,wall:'white',ambient:15},bd:{on:true,color:'#8e9196',gap:0.3},subj:{type:'person',bd:1.8,x:0,rot:0,count:10},cam:{dist:3.2,height:1.55,focal:85,N:5.6,t:1\/125,ISO:400,wb:5600,portrait:true},view:{dims:true,marks:true,tags:true},lights:[mkLight(Object.assign({name:'Key',role:'key'},ROLES.key.o,{az:45,dist:1.6,height:2.15})),mkLight(Object.assign({name:'Fill',role:'fill'},ROLES.fill.o,{power:60,dist:2.6}))]});}\nlet ST=(()=>{try{const s=JSON.parse(localStorage.getItem('kblack_lab_st')||'null');if(s&&s.room&&s.lights)return migrateST(s);}catch(e){}return defaultST();})();\nlet SELL=ST.lights[0]?ST.lights[0].id:null;\nlet saveT=null;function saveSoon(){clearTimeout(saveT);saveT=setTimeout(()=>{try{localStorage.setItem('kblack_lab_st',JSON.stringify(ST));}catch(e){}},400);}\n\n\/* geometry & photometry *\/\nfunction groupLayout(){if(ST.subj.type!=='group')return [{x:0,z:0,h:1,row:0}];const n=clamp(Math.round(ST.subj.count||10),2,40);const per=Math.min(8,Math.max(3,Math.ceil(Math.sqrt(n*2.2))));const out=[];let k=0,r=0;while(k<n){const m=Math.min(per,n-k);for(let i=0;i<m;i++){out.push({x:(i-(m-1)\/2)*0.58+(r%2?0.29:0),z:-r*0.62,h:1+(((k*37)%7)-3)*0.012,row:r});k++;}r++;}return out;}\nfunction geo(){const r=ST.room;const bz=-r.l\/2+ST.bd.gap;const bx=ST.bd.x||0;const sz=bz+ST.subj.bd;const sx=ST.subj.x;const H=subjH();const faceY=ST.subj.type==='product'?0.95:H*0.93;const ca=rad(ST.cam.az||0);const cx0=sx+Math.sin(ca)*ST.cam.dist,cz0=sz+Math.cos(ca)*ST.cam.dist;const camX=clamp(cx0,-r.w\/2+0.15,r.w\/2-0.15),camZ=clamp(cz0,-r.l\/2+0.15,r.l\/2-0.15);const camClamped=Math.abs(camX-cx0)>0.01||Math.abs(camZ-cz0)>0.01;const lay=groupLayout();const faces=lay.map(p=>V(sx+p.x,faceY*p.h,sz+p.z));let cx=0,cz=0;faces.forEach(f=>{cx+=f.x;cz+=f.z;});cx\/=faces.length;cz\/=faces.length;return {H,bx,bz,sz,sx,faceY,camRaw:sz+ST.cam.dist,camClamped,cam:V(camX,ST.cam.height,camZ),face:V(sx,faceY,sz),faces,lay,center:V(cx,faceY,cz)};}\nfunction camAim(g){const d=vnrm(vsub(g.face,g.cam));let yaw=Math.atan2(d.x,d.z),pit=Math.asin(clamp(d.y,-1,1));yaw-=rad(ST.cam.pan||0);pit+=rad(ST.cam.tilt||0);return V(g.cam.x+Math.sin(yaw)*Math.cos(pit),g.cam.y+Math.sin(pit),g.cam.z+Math.cos(yaw)*Math.cos(pit));}\nfunction camDist(g){return Math.hypot(g.cam.x-g.sx,g.cam.z-g.sz);}\nfunction groupWidth(g){let mn=1e9,mx=-1e9;g.faces.forEach(f=>{mn=Math.min(mn,f.x);mx=Math.max(mx,f.x);});return mx-mn+0.6;}\nfunction modDepth(L){const md=modOf(L),m=md.m;if(m.shape==='rect')return Math.min(.55,.25+Math.max(md.w,md.h)*.18);if(L.mod==='para')return md.w*.45;if(L.mod==='umb')return md.w*.2;if(L.mod==='dish')return .16;if(m.shape==='oct')return Math.min(.55,.25+md.w*.18);return L.mod==='fresnel'?.05:.2;}\nfunction mountPos(L,g){const lp=lightPos(L,g),tp=aimPt(L,g);const d=vnrm(vsub(tp,lp));const k=modDepth(L)+0.13;return V(lp.x-d.x*k,lp.y-d.y*k,lp.z-d.z*k);}\nfunction standBase(L,g){const mp=mountPos(L,g);if(!L.boom)return V(mp.x,0,mp.z);const r=ST.room;const s=Math.sin(rad(L.az))>=0?1:-1;return V(clamp(mp.x+s*1.35,-r.w\/2+0.25,r.w\/2-0.25),0,clamp(mp.z-0.35,-r.l\/2+0.25,r.l\/2-0.25));}\nfunction wallCoords(p){const r=ST.room;return 'c\u00e1ch t\u01b0\u1eddng sau '+(p.z+r.l\/2).toFixed(2)+' m, t\u01b0\u1eddng tr\u00e1i '+(p.x+r.w\/2).toFixed(2)+' m';}\nfunction wrapAz(a){return ((Math.round(a)+180)%360+360)%360-180;}\nfunction azFmt(v){v=wrapAz(v);if(v===0)return 'th\u1eb3ng tr\u01b0\u1edbc m\u1eb7t';if(Math.abs(v)===180)return 'th\u1eb3ng sau l\u01b0ng';return (v>0?'ph\u1ea3i ':'tr\u00e1i ')+Math.abs(v)+'\u00b0'+(Math.abs(v)>95?' (sau l\u01b0ng)':Math.abs(v)<85?' (tr\u01b0\u1edbc m\u1eb7t)':' (ngang h\u00f4ng)');}\nfunction softTxt(s){return s>0.8?'r\u1ea5t m\u1ec1m':s>0.45?'m\u1ec1m':s>0.2?'trung t\u00ednh':'c\u1ee9ng';}\nfunction lightPos(L,g){return V(g.sx+Math.sin(rad(L.az))*L.dist,L.height,g.sz+Math.cos(rad(L.az))*L.dist);}\nfunction aimPt(L,g){const lp=lightPos(L,g);const c=g.center;if(L.aim==='bg')return V(L.bgX!=null?g.bx+L.bgX:lp.x*0.5+g.bx*0.5,L.bgY!=null?L.bgY:1.35,g.bz+0.03);if(L.aim==='body')return V(c.x,ST.subj.type==='product'?0.8:g.H*0.67,c.z);if(L.aim==='hair')return V(c.x,ST.subj.type==='product'?1.05:g.H*1.035,c.z-0.05);return V(c.x,c.y,c.z);}\nfunction modOf(L){const m=MODS[L.mod]||MODS.softbox;const s=m.sizes[Math.min(L.size,m.sizes.length-1)];let spread=m.spread,eff=m.eff;if(L.grid){spread*=0.55;eff*=0.85;}return {m,w:s[0],h:s[1],label:s[2],spread,eff};}\nfunction lumens(L){return L.kind==='flash'?L.power*8\/ST.cam.t:L.power*70;}\nfunction photo(L){const md=modOf(L);const Phi=lumens(L)*md.eff*gelOf(L).t;const areaShare=md.m.area?0.45:0;const half=rad(md.spread\/2);const omega=2*Math.PI*(1-Math.cos(half));const Is=Phi*(1-areaShare)\/omega;const A=md.m.shape==='rect'?md.w*md.h:Math.PI*Math.pow(md.w\/2,2);const La=areaShare?Phi*areaShare\/(A*Math.PI):0;return {md,Phi,Is,La,A,half,pen:md.m.area?1:(L.mod==='fresnel'?0.15:0.35)};}\nfunction illum(L,P,n,g){const lp=lightPos(L,g),tp=aimPt(L,g);const ph=photo(L);const v=vsub(lp,P);const d=Math.max(0.15,vlen(v));const vn=vscl(v,1\/d);const ci=n?Math.max(0,vdot(n,vn)):1;const axis=vnrm(vsub(tp,lp));const co=vdot(axis,vscl(vn,-1));const f=smooth(Math.cos(ph.half),Math.cos(ph.half*(1-ph.pen)),co);return {E:ph.Is*f*ci\/(d*d)+ph.La*ph.A*Math.max(0,co)*ci\/(d*d),d};}\nfunction bounceLux(){const r=ST.room;let Phi=0;ST.lights.forEach(L=>{if(L.on)Phi+=photo(L).Phi;});const S=2*(r.w*r.l+r.w*r.h+r.l*r.h);return WALLS[r.wall].r*Phi\/S*0.9;}\nfunction faceTotal(P,n,g){let t=0;ST.lights.forEach(L=>{if(L.on)t+=illum(L,P,n,g).E;});return t;}\nfunction meter(){const g=geo();const n=vnrm(vsub(g.cam,g.face));let tot=0;const per=ST.lights.map(L=>{if(!L.on)return null;const a=illum(L,g.face,n,g),b=illum(L,g.face,null,g);tot+=a.E;return {toCam:a.E,inc:b.E,d:a.d};});const amb=ST.room.ambient+bounceLux();tot+=amb;let grp=null;\n if(ST.subj.type==='group'){const vals=g.faces.map(f=>faceTotal(f,vnrm(vsub(g.cam,f)),g)+amb);const mn=Math.min.apply(null,vals),mx=Math.max.apply(null,vals);const avg=vals.reduce((a,b)=>a+b,0)\/vals.length;grp={mn,mx,avg,spread:Math.log2(mx\/Math.max(0.01,mn)),n:vals.length};tot=avg;}\n const c=ST.cam;const Nrec=Math.sqrt(tot*c.t*c.ISO\/250);const ev=Math.log2((tot*c.t*c.ISO\/250)\/(c.N*c.N));return {tot,amb,per,Nrec,ev,grp};}\nfunction warnings(){const r=ST.room,g=geo(),W=[];ST.lights.forEach(L=>{if(!L.on)return;const p=lightPos(L,g);const a=Math.abs(wrapAz(L.az));\n if(Math.abs(p.x)>r.w\/2-0.1||p.z<-r.l\/2+0.1||p.z>r.l\/2-0.1)W.push(L.name+' n\u1eb1m ngo\u00e0i t\u01b0\u1eddng \u2014 ph\u00f2ng kh\u00f4ng \u0111\u1ee7 ch\u1ed7');\n if(L.height>r.h-0.15)W.push(L.name+' cao qu\u00e1 tr\u1ea7n');\n if(ST.bd.on&&L.aim!=='bg'&&p.z<g.bz-0.02)W.push(L.name+' \u0111ang n\u1eb1m sau ph\u00f4ng n\u1ec1n');\n if(L.role==='rim'&&a<110)W.push(L.name+' l\u00e0 \u0111\u00e8n vi\u1ec1n nh\u01b0ng \u0111ang \u1edf '+(a<85?'ph\u00eda tr\u01b0\u1edbc':'ngang h\u00f4ng')+' \u2014 \u0111\u01b0a ra sau l\u01b0ng, g\u00f3c 120\u00b0\u2013170\u00b0');\n if(L.role==='kicker'&&a<95)W.push(L.name+' (kicker) n\u00ean \u1edf sau-b\u00ean, g\u00f3c 100\u00b0\u2013140\u00b0');\n if(L.role==='hair'&&a<110&&L.dist>0.8)W.push(L.name+' (t\u00f3c) n\u00ean treo tr\u00ean \u0111\u1ea7u ho\u1eb7c sau l\u01b0ng');\n if(L.role==='bg'&&L.aim!=='bg')W.push(L.name+' l\u00e0 \u0111\u00e8n n\u1ec1n nh\u01b0ng kh\u00f4ng chi\u1ebfu v\u00e0o ph\u00f4ng');\n if(!L.boom&&L.dist<0.8&&L.height>g.faceY+0.4)W.push(L.name+': ch\u00e2n \u0111\u00e8n \u0111\u1ee9ng s\u00e1t ch\u1ee7 th\u1ec3, s\u1ebd l\u1ecdt khung \u2014 b\u1eadt ch\u00e2n boom');\n if(L.kind==='flash'&&ST.cam.t<1\/250)W.push('T\u1ed1c '+fmtT(ST.cam.t)+' v\u01b0\u1ee3t \u0111\u1ed3ng b\u1ed9 flash \u2014 c\u1ea7n HSS');});\n if(g.camClamped)W.push('M\u00e1y \u1ea3nh ch\u1ea1m t\u01b0\u1eddng \u2014 ch\u1ec9 \u0111\u1eb7t \u0111\u01b0\u1ee3c c\u00e1ch ch\u1ee7 th\u1ec3 '+camDist(g).toFixed(1)+' m \u1edf g\u00f3c n\u00e0y');\n if(ST.subj.type==='group'){const gw=groupWidth(g);const hf=2*Math.atan(sensorH()\/2\/ST.cam.focal);const need=gw\/2\/Math.tan(hf\/2);if(need>camDist(g)+0.01)W.push('Khung ch\u01b0a l\u1ea5y h\u1ebft nh\u00f3m (r\u1ed9ng '+gw.toFixed(1)+' m) \u2014 c\u1ea7n l\u00f9i '+need.toFixed(1)+' m ho\u1eb7c d\u00f9ng \u1ed1ng r\u1ed9ng h\u01a1n');}\n if(ST.bd.on&&ST.subj.bd>0.45+bdFloor()-0.15)W.push('Ng\u01b0\u1eddi m\u1eabu \u0111\u1ee9ng ngo\u00e0i ph\u1ea7n ph\u00f4ng tr\u1ea3i s\u00e0n \u2014 ch\u00e2n s\u1ebd l\u1ed9 s\u00e0n th\u1eadt, tr\u1ea3i ph\u00f4ng d\u00e0i th\u00eam '+(ST.subj.bd-0.45-bdFloor()+0.3).toFixed(1)+' m');\n if(ST.bd.on&&Math.abs(g.sx-g.bx)>bdW()\/2-0.3)W.push('Ng\u01b0\u1eddi m\u1eabu \u0111\u1ee9ng l\u1ec7ch ra m\u00e9p ph\u00f4ng');\n if(ST.bd.on&&ST.subj.type==='group'&&groupWidth(g)>bdW()-0.2)W.push('Nh\u00f3m r\u1ed9ng '+groupWidth(g).toFixed(1)+' m, ph\u00f4ng ch\u1ec9 '+bdW().toFixed(2)+' m \u2014 ch\u1ecdn kh\u1ed5 ph\u00f4ng l\u1edbn h\u01a1n');\n if(ST.lights.some(L=>L.on&&L.kind==='led')&&ST.cam.t>1\/60)W.push('T\u1ed1c ch\u1eadm h\u01a1n 1\/60 d\u1ec5 rung tay');return [...new Set(W)];}\n\/* ----- Studio UI ----- *\/\nlet UNDO=[],REDO=[],LASTSNAP=null,histT=null;\nfunction histSave(){clearTimeout(histT);histT=setTimeout(histFlush,450);}\nfunction histFlush(){const cur=JSON.stringify(ST);if(LASTSNAP!==null&&cur!==LASTSNAP){UNDO.push(LASTSNAP);if(UNDO.length>60)UNDO.shift();REDO.length=0;}LASTSNAP=cur;updUndo();}\nfunction updUndo(){const u=$('btnUndo'),r=$('btnRedo');if(u)u.disabled=!UNDO.length;if(r)r.disabled=!REDO.length;}\nfunction restoreSnap(s){ST=migrateST(JSON.parse(s));LASTSNAP=s;if(!ST.lights.find(L=>L.id===SELL))SELL=ST.lights[0]?ST.lights[0].id:null;buildLeft();buildRight();DIRTY=true;drawPlan($('plan'));updateMeter();saveSoon();syncOrientBtn();syncViewBtns();updUndo();}\nfunction doUndo(){clearTimeout(histT);histFlush();if(!UNDO.length)return;REDO.push(JSON.stringify(ST));restoreSnap(UNDO.pop());toast('\u0110\u00e3 ho\u00e0n t\u00e1c');}\nfunction doRedo(){clearTimeout(histT);if(!REDO.length)return;UNDO.push(JSON.stringify(ST));restoreSnap(REDO.pop());toast('\u0110\u00e3 l\u00e0m l\u1ea1i');}\nfunction changed(struct){USER_ACTED=true;DIRTY=true;drawPlan($('plan'));updateMeter();saveSoon();histSave();if(struct)buildRight();}\nfunction buildLeft(){const P=$('spLeft');P.innerHTML='';\n const g0=el('div','grp','<h4>Setup m\u1eabu <small>\u00e1p v\u00e0o ph\u00f2ng hi\u1ec7n t\u1ea1i<\/small><\/h4>');const pr=el('div','presets');Object.keys(SETUP_TXT).forEach(k=>{const b=el('button',null,SETUP_TXT[k][0]);b.title=SETUP_TXT[k][1];b.onclick=()=>applyPreset(k);pr.appendChild(b);});g0.appendChild(pr);P.appendChild(g0);\n const r=ST.room;const g1=el('div','grp','<h4>Ph\u00f2ng ch\u1ee5p <small id=\"roomArea\"><\/small><\/h4>');\n const area=()=>{const a=$('roomArea');if(a)a.textContent=(r.w*r.l).toFixed(0)+' m\u00b2';};\n g1.appendChild(sld('Chi\u1ec1u r\u1ed9ng',2,15,0.1,r.w,v=>v.toFixed(1)+' m',v=>{r.w=v;area();changed();}));\n g1.appendChild(sld('Chi\u1ec1u d\u00e0i',2,20,0.1,r.l,v=>v.toFixed(1)+' m',v=>{r.l=v;area();changed();}));\n g1.appendChild(sld('Tr\u1ea7n cao',2.4,8,0.1,r.h,v=>v.toFixed(1)+' m',v=>{r.h=v;changed();}));\n g1.appendChild(selc('M\u00e0u t\u01b0\u1eddng (\u1ea3nh h\u01b0\u1edfng \u00e1nh s\u00e1ng h\u1eaft)',Object.keys(WALLS).map(k=>[k,WALLS[k].n]),r.wall,v=>{r.wall=v;changed();}));\n g1.appendChild(sld('\u00c1nh s\u00e1ng m\u00f4i tr\u01b0\u1eddng',0,400,5,r.ambient,v=>v+' lux',v=>{r.ambient=v;changed();}));\n g1.appendChild(el('div','note','\u0110\u00e8n ph\u00f2ng th\u01b0\u1eddng 100\u2013300 lux. T\u1eaft h\u1ebft \u0111\u1ec3 ki\u1ec3m so\u00e1t s\u00e1ng ho\u00e0n to\u00e0n.'));P.appendChild(g1);setTimeout(area);\n const b=ST.bd;const g2=el('div','grp','<h4>Ph\u00f4ng n\u1ec1n <small>k\u00e9o ph\u00f4ng trong khung 3D \u0111\u1ec3 d\u1eddi<\/small><\/h4>');g2.appendChild(segc([[1,'C\u00f3 ph\u00f4ng'],[0,'Kh\u00f4ng']],b.on?1:0,v=>{b.on=!!v;changed();}));\n const sw=el('div','bdsw');BDCOL.forEach(c=>{const x=el('button','bds'+(b.color===c[0]?' on':''));x.style.background=c[0];x.title=c[1];x.setAttribute('aria-label','Ph\u00f4ng '+c[1]);x.onclick=()=>{b.color=c[0];changed();buildLeft();};sw.appendChild(x);});\n const cp=document.createElement('input');cp.type='color';cp.value=b.color;cp.className='bds pick';cp.title='Ch\u1ecdn m\u00e0u kh\u00e1c';cp.setAttribute('aria-label','Ch\u1ecdn m\u00e0u ph\u00f4ng kh\u00e1c');cp.oninput=()=>{b.color=cp.value;changed();};cp.onchange=()=>buildLeft();sw.appendChild(cp);g2.appendChild(sw);\n g2.appendChild(el('div','note',(BDCOL.find(c=>c[0]===b.color)||[0,'M\u00e0u tu\u1ef3 ch\u1ecdn'])[1]+' \u00b7 '+b.color.toUpperCase()));\n g2.appendChild(el('div','ctl',''));g2.appendChild(segc([[0,'Gi\u1ea5y tr\u01a1n'],[1,'Canvas loang']],b.tex?1:0,v=>{b.tex=!!v;changed();}));\n g2.appendChild(el('div','ctl',''));g2.appendChild(segc([[1.35,'Kh\u1ed5 1,35 m'],[2.72,'2,72 m'],[3.55,'3,55 m']],b.w,v=>{b.w=+v;clampBd();changed();}));\n g2.appendChild(el('div','ctl',''));g2.appendChild(sld('Tr\u1ea3i ph\u00f4ng ra s\u00e0n',0.5,5,0.1,b.floor||2.2,v=>v.toFixed(1)+' m',v=>{b.floor=v;changed();}));\n g2.appendChild(el('div','ctl',''));\n g2.appendChild(sld('Ph\u00f4ng c\u00e1ch t\u01b0\u1eddng sau',0.1,Math.max(0.2,ST.room.l-1),0.05,b.gap,v=>v.toFixed(2)+' m',v=>{moveBd(b.x,v);changed();}));\n g2.appendChild(sld('D\u1eddi ph\u00f4ng tr\u00e1i \/ ph\u1ea3i',-3,3,0.05,b.x,v=>(v>0?'ph\u1ea3i ':v<0?'tr\u00e1i ':'')+Math.abs(v).toFixed(2)+' m',v=>{moveBd(v,b.gap);changed();}));\n g2.appendChild(el('div','note','D\u1eddi ph\u00f4ng th\u00ec ng\u01b0\u1eddi m\u1eabu \u0111\u1ee9ng y\u00ean t\u1ea1i ch\u1ed7.'));P.appendChild(g2);\n const s=ST.subj;const g3=el('div','grp','<h4>Ch\u1ee7 th\u1ec3<\/h4>');g3.appendChild(segc([['person','1 ng\u01b0\u1eddi'],['group','Nh\u00f3m \u0111\u00f4ng'],['product','S\u1ea3n ph\u1ea9m']],s.type,v=>{s.type=v;changed();buildLeft();}));if(s.type!=='product'){g3.appendChild(el('div','ctl',''));g3.appendChild(charListEl());const ch=charById(s.char);if(ch&&s.char!=='all')g3.appendChild(faceFixEl(ch));}\n if(s.type==='group'){g3.appendChild(el('div','ctl',''));g3.appendChild(sld('S\u1ed1 ng\u01b0\u1eddi',2,40,1,s.count,v=>v+' ng\u01b0\u1eddi',v=>{s.count=v;changed();}));}\n g3.appendChild(el('div','ctl',''));g3.appendChild(sld(s.type==='group'?'H\u00e0ng \u0111\u1ea7u c\u00e1ch ph\u00f4ng':'C\u00e1ch ph\u00f4ng',0.4,6,0.05,s.bd,v=>v.toFixed(2)+' m',v=>{s.bd=v;changed();}));\n g3.appendChild(sld('L\u1ec7ch tr\u00e1i \/ ph\u1ea3i',-2,2,0.05,s.x,v=>(v>0?'ph\u1ea3i ':v<0?'tr\u00e1i ':'')+Math.abs(v).toFixed(2)+' m',v=>{s.x=v;changed();}));\n g3.appendChild(sld('Xoay ng\u01b0\u1eddi',-180,180,5,s.rot||0,v=>v+'\u00b0',v=>{s.rot=v;changed();}));\n g3.appendChild(el('div','note','K\u00e9o ch\u1ee7 th\u1ec3 tr\u1ef1c ti\u1ebfp trong khung 3D ho\u1eb7c tr\u00ean m\u1eb7t b\u1eb1ng. C\u00e0ng xa ph\u00f4ng, ph\u00f4ng c\u00e0ng t\u1ed1i v\u00e0 d\u1ec5 t\u00e1ch n\u1ec1n.'));P.appendChild(g3);\n const c=ST.cam;const g4=el('div','grp','<h4>M\u00e1y \u1ea3nh<\/h4>');\n g4.appendChild(sld('C\u00e1ch ch\u1ee7 th\u1ec3',0.5,12,0.05,c.dist,v=>v.toFixed(2)+' m',v=>{c.dist=v;changed();camNeed();}));\n g4.appendChild(sld('\u0110\u1ed9 cao m\u00e1y',0.4,2.5,0.05,c.height,v=>v.toFixed(2)+' m',v=>{c.height=v;changed();}));\n g4.appendChild(sld('G\u00f3c m\u00e1y quanh ch\u1ee7 th\u1ec3',-170,170,5,c.az||0,v=>v===0?'ch\u00ednh di\u1ec7n':azFmt(v),v=>{c.az=v;changed();}));\n g4.appendChild(sld('Ng\u1eafm l\u00ean \/ xu\u1ed1ng',-35,35,1,c.tilt||0,v=>v===0?'v\u00e0o m\u1eb7t':(v>0?'l\u00ean ':'xu\u1ed1ng ')+Math.abs(v)+'\u00b0',v=>{c.tilt=v;changed();}));\n g4.appendChild(sld('Ng\u1eafm tr\u00e1i \/ ph\u1ea3i',-35,35,1,c.pan||0,v=>v===0?'v\u00e0o m\u1eb7t':(v>0?'ph\u1ea3i ':'tr\u00e1i ')+Math.abs(v)+'\u00b0',v=>{c.pan=v;changed();}));\n g4.appendChild(selc('Ti\u00eau c\u1ef1',FOC.map(f=>[f,f+'mm']),c.focal,v=>{c.focal=+v;changed();camNeed();}));\n const row=el('div','row2');row.appendChild(selc('Kh\u1ea9u',SAP.map(a=>[a,'f\/'+a]),c.N,v=>{c.N=+v;changed();}));row.appendChild(selc('T\u1ed1c',SSH.map(t=>[t,fmtT(t)]),c.t,v=>{c.t=+v;changed();}));g4.appendChild(row);\n const row2=el('div','row2');row2.appendChild(selc('ISO',SIS.map(i=>[i,i]),c.ISO,v=>{c.ISO=+v;changed();}));row2.appendChild(selc('Khung h\u00ecnh',ASPECTS.map(a=>[a[0],a[0]+(a[1]<1?' d\u1ecdc':a[1]>1?' ngang':' vu\u00f4ng')]),c.aspect,v=>{setAspect(v);}));g4.appendChild(row2);\n g4.appendChild(sld('C\u00e2n b\u1eb1ng tr\u1eafng',2500,10000,100,c.wb,v=>v+'K',v=>{c.wb=v;changed();}));\n g4.appendChild(el('div','note','<span id=\"camNeed\"><\/span>'));P.appendChild(g4);camNeed();}\nfunction camNeed(){const e=$('camNeed');if(!e)return;const c=ST.cam;const sv=sensorV();const f=c.focal;const g=geo();const maxD=ST.room.l\/2-0.15-g.sz;\n if(ST.subj.type==='group'){const gw=groupWidth(g);const need=f*gw\/sensorH();e.innerHTML='Nh\u00f3m r\u1ed9ng '+gw.toFixed(1)+' m \u2014 v\u1edbi '+f+'mm khung '+(c.portrait?'d\u1ecdc':'ngang')+' c\u1ea7n l\u00f9i '+need.toFixed(1)+' m'+(need>maxD?' (ph\u00f2ng ch\u1ec9 cho l\u00f9i '+maxD.toFixed(1)+' m \u2014 d\u00f9ng \u1ed1ng r\u1ed9ng h\u01a1n)':'')+'.';return;}\n const shots=[['C\u1eadn m\u1eb7t',0.45],['N\u1eeda ng\u01b0\u1eddi',0.95],['To\u00e0n th\u00e2n',1.95]];e.innerHTML='V\u1edbi '+f+'mm, khung '+(c.portrait?'d\u1ecdc':'ngang')+': '+shots.map(s=>{const d=f*s[1]\/sv;return s[0]+' '+d.toFixed(1)+' m'+(d>maxD?' (ph\u00f2ng kh\u00f4ng \u0111\u1ee7)':'');}).join(', ')+'. Ph\u00f2ng cho l\u00f9i t\u1ed1i \u0111a '+maxD.toFixed(1)+' m.';}\nfunction nudge(items){const w=el('div','nudge');items.forEach(it=>{const b=el('button',null,it[0]);b.onclick=()=>{it[1]();changed();buildRight();};w.appendChild(b);});return w;}\nfunction addRoleLight(k){if(ST.lights.length>=5){toast('T\u1ed1i \u0111a 5 \u0111\u00e8n');return;}const base=ROLE_NAME[k];let name=base,i=2;while(ST.lights.some(L=>L.name===name))name=base+' '+(i++);const o=Object.assign({},ROLES[k].o);if(ST.lights.some(L=>L.role===k)&&['key','fill','rim','kicker'].indexOf(k)>=0)o.az=wrapAz(-o.az);const L=mkLight(Object.assign({name,role:k},o));ST.lights.push(L);SELL=L.id;changed(true);toast('\u0110\u00e3 th\u00eam '+name+' \u2014 '+azFmt(L.az));}\nfunction buildRight(){const P=$('spRight');P.innerHTML='';P.appendChild(missionBox());const g=el('div','grp','<h4>\u0110\u00e8n <small>'+ST.lights.length+'\/5<\/small><\/h4>');\n ST.lights.forEach((L,i)=>{const md=modOf(L);const row=el('div','lrow'+(L.id===SELL?' on':''));row.innerHTML='<span class=\"d\" style=\"background:'+(L.on?LCOLS[i%5]:'#3a4460')+'\"><\/span><span class=\"n\">'+L.name+(L.gel?' <i class=\"geld\" style=\"background:'+L.gel+'\"><\/i>':'')+'<small>'+roleShort(L.role)+' \u00b7 '+md.m.n+' '+md.label+(L.boom?' \u00b7 boom':'')+'<\/small><\/span>';const tg=el('button','tg'+(L.on?' on':''));tg.setAttribute('aria-label','B\u1eadt t\u1eaft '+L.name);tg.onclick=e=>{e.stopPropagation();L.on=!L.on;changed(true);};row.appendChild(tg);row.onclick=()=>{SELL=L.id;buildRight();drawPlan($('plan'));DIRTY=true;};g.appendChild(row);});\n if(ST.lights.length<5){const wrap=el('div','addrow');const rs=document.createElement('select');rs.setAttribute('aria-label','Vai tr\u00f2 \u0111\u00e8n m\u1edbi');Object.keys(ROLES).forEach(k=>{const o=document.createElement('option');o.value=k;o.textContent=ROLES[k].n;rs.appendChild(o);});const used=ST.lights.map(x=>x.role);rs.value=['key','fill','rim','bg','hair','top','kicker'].find(k=>used.indexOf(k)<0)||'fill';const ab=el('button','pbtn2','+ Th\u00eam');ab.onclick=()=>addRoleLight(rs.value);wrap.append(rs,ab);g.appendChild(wrap);g.appendChild(el('div','note','Ch\u1ecdn vai tr\u00f2 r\u1ed3i b\u1ea5m Th\u00eam \u2014 \u0111\u00e8n \u0111\u01b0\u1ee3c \u0111\u1eb7t \u0111\u00fang v\u1ecb tr\u00ed chu\u1ea9n: rim sau l\u01b0ng, t\u00f3c v\u00e0 \u0111\u1ec9nh treo boom tr\u00ean \u0111\u1ea7u, \u0111\u00e8n n\u1ec1n chi\u1ebfu ph\u00f4ng.'));}\n P.appendChild(g);const L=ST.lights.find(x=>x.id===SELL);if(!L){updHUD();return;}const E=el('div','edit');\n const nm=document.createElement('input');nm.type='text';nm.value=L.name;nm.setAttribute('aria-label','T\u00ean \u0111\u00e8n');nm.oninput=()=>{L.name=nm.value||'\u0110\u00e8n';drawPlan($('plan'));updateMeter();saveSoon();};E.appendChild(nm);E.appendChild(el('div','ctl',''));\n const rr=el('div','row2');rr.appendChild(selc('Vai tr\u00f2',Object.keys(ROLES).map(k=>[k,roleShort(k)]),L.role,v=>{L.role=v;changed(true);}));const rb=el('button','gbtn','\u0110\u1eb7t v\u1ecb tr\u00ed chu\u1ea9n');rb.style.cssText='align-self:end;margin-bottom:10px;padding:7px 8px;font-size:12px';rb.onclick=()=>{Object.assign(L,ROLES[L.role].o);changed(true);toast('\u0110\u00e3 \u0111\u01b0a '+L.name+' v\u1ec1 v\u1ecb tr\u00ed chu\u1ea9n');};rr.appendChild(rb);E.appendChild(rr);\n E.appendChild(segc([['led','LED li\u00ean t\u1ee5c'],['flash','Flash']],L.kind,v=>{L.kind=v;changed(true);}));E.appendChild(el('div','ctl',''));\n E.appendChild(sld(L.kind==='flash'?'C\u00f4ng su\u1ea5t (Ws)':'C\u00f4ng su\u1ea5t (W)',L.kind==='flash'?50:20,1200,10,L.power,v=>v+(L.kind==='flash'?' Ws':' W'),v=>{L.power=v;changed();}));\n E.appendChild(selc('B\u1ed9 t\u1ea3n s\u00e1ng',Object.keys(MODS).map(k=>[k,MODS[k].n]),L.mod,v=>{L.mod=v;L.size=Math.min(L.size,MODS[v].sizes.length-1);changed(true);}));\n const m=MODS[L.mod];E.appendChild(selc('K\u00edch th\u01b0\u1edbc',m.sizes.map((s,i)=>[i,s[2]+' cm']),L.size,v=>{L.size=+v;changed(true);}));\n E.appendChild(segc([[0,'Kh\u00f4ng t\u1ed5 ong'],[1,'T\u1ed5 ong (grid)']],L.grid?1:0,v=>{L.grid=!!v;changed(true);}));E.appendChild(el('div','ctl',''));\n E.appendChild(segc([[0,'Ch\u00e2n \u0111\u1ee9ng'],[1,'Ch\u00e2n boom (treo)']],L.boom?1:0,v=>{L.boom=!!v;changed(true);}));\n E.appendChild(el('div','sect','V\u1ecb tr\u00ed \u2014 k\u00e9o tr\u1ef1c ti\u1ebfp trong khung 3D, gi\u1eef Shift \u0111\u1ec3 n\u00e2ng h\u1ea1'));\n E.appendChild(sld('G\u00f3c quanh ch\u1ee7 th\u1ec3',-180,180,1,wrapAz(L.az),azFmt,v=>{L.az=v;changed();}));\n E.appendChild(nudge([['\u221215\u00b0',()=>L.az=wrapAz(L.az-15)],['\u22125\u00b0',()=>L.az=wrapAz(L.az-5)],['+5\u00b0',()=>L.az=wrapAz(L.az+5)],['+15\u00b0',()=>L.az=wrapAz(L.az+15)]]));\n E.appendChild(sld('Kho\u1ea3ng c\u00e1ch t\u1edbi ch\u1ee7 th\u1ec3',0.3,8,0.05,L.dist,v=>v.toFixed(2)+' m',v=>{L.dist=v;changed();}));\n E.appendChild(nudge([['\u22120,5 m',()=>L.dist=clamp(+(L.dist-0.5).toFixed(2),0.3,8)],['\u22120,1',()=>L.dist=clamp(+(L.dist-0.1).toFixed(2),0.3,8)],['+0,1',()=>L.dist=clamp(+(L.dist+0.1).toFixed(2),0.3,8)],['+0,5 m',()=>L.dist=clamp(+(L.dist+0.5).toFixed(2),0.3,8)]]));\n const hmax=Math.max(1,ST.room.h-0.1);E.appendChild(sld('\u0110\u1ed9 cao t\u00e2m \u0111\u00e8n',0.2,hmax,0.05,L.height,v=>v.toFixed(2)+' m',v=>{L.height=v;changed();}));\n E.appendChild(nudge([['\u22120,5 m',()=>L.height=clamp(+(L.height-0.5).toFixed(2),0.2,hmax)],['\u22120,1',()=>L.height=clamp(+(L.height-0.1).toFixed(2),0.2,hmax)],['+0,1',()=>L.height=clamp(+(L.height+0.1).toFixed(2),0.2,hmax)],['+0,5 m',()=>L.height=clamp(+(L.height+0.5).toFixed(2),0.2,hmax)]]));\n E.appendChild(selc('H\u01b0\u1edbng chi\u1ebfu',[['face','V\u00e0o m\u1eb7t'],['body','V\u00e0o th\u00e2n'],['hair','V\u00e0o t\u00f3c \/ vai'],['bg','V\u00e0o ph\u00f4ng']],L.aim,v=>{L.aim=v;changed();}));\n E.appendChild(sld('Nhi\u1ec7t \u0111\u1ed9 m\u00e0u',2700,7500,100,L.kelvin,v=>v+'K',v=>{L.kelvin=v;changed();}));\n const gw=el('div','ctl');gw.appendChild(el('div','ctlh','<span>Gel m\u00e0u<\/span><b>'+(L.gel?(GELS.find(x=>x[0]===L.gel)||[0,'Tu\u1ef3 ch\u1ecdn'])[1]+' \u00b7 m\u1ea5t '+(Math.log2(1\/gelOf(L).t)).toFixed(1)+' stop':'Kh\u00f4ng')+'<\/b>'));const gs=el('div','gelsw');GELS.forEach(gl=>{const x=el('button','gel'+(L.gel===gl[0]?' on':'')+(gl[0]?'':' none'),gl[0]?'':'\u2205');if(gl[0])x.style.background=gl[0];x.title=gl[1];x.setAttribute('aria-label','Gel '+gl[1]);x.onclick=()=>{L.gel=gl[0];changed(true);};gs.appendChild(x);});const gp=document.createElement('input');gp.type='color';gp.className='gel pick';gp.value=L.gel||'#ff4fb0';gp.title='Gel m\u00e0u kh\u00e1c';gp.oninput=()=>{L.gel=gp.value;changed();};gp.onchange=()=>buildRight();gs.appendChild(gp);gw.appendChild(gs);E.appendChild(gw);\n if(L.aim==='bg'){const g=geo();const lp=lightPos(L,g);const ax=L.bgX!=null?L.bgX:(lp.x-g.bx)*0.5;E.appendChild(el('div','sect','\u0110i\u1ec3m r\u1ecdi tr\u00ean ph\u00f4ng'));E.appendChild(sld('Cao \/ th\u1ea5p',0.2,2.6,0.05,L.bgY!=null?L.bgY:1.35,v=>v.toFixed(2)+' m',v=>{L.bgY=v;changed();}));E.appendChild(sld('L\u1ec7ch tr\u00e1i \/ ph\u1ea3i',-1.8,1.8,0.05,ax,v=>(v>0?'ph\u1ea3i ':v<0?'tr\u00e1i ':'gi\u1eefa ')+Math.abs(v).toFixed(2)+' m',v=>{L.bgX=v;changed();}));}\n const info=el('div','note');info.id='lInfo';E.appendChild(info);\n const mb=el('div','minib');const dp=el('button',null,'Nh\u00e2n b\u1ea3n \u0111\u1ed1i x\u1ee9ng');dp.onclick=()=>{if(ST.lights.length>=5){toast('T\u1ed1i \u0111a 5 \u0111\u00e8n');return;}const c=JSON.parse(JSON.stringify(L));c.id=lid();c.name=L.name+' 2';c.az=wrapAz(-L.az);ST.lights.push(c);SELL=c.id;changed(true);};const dl=el('button','dg','Xo\u00e1 \u0111\u00e8n');dl.onclick=()=>{ST.lights=ST.lights.filter(x=>x.id!==L.id);SELL=ST.lights[0]?ST.lights[0].id:null;changed(true);};mb.append(dp,dl);E.appendChild(mb);\n P.appendChild(E);updateLInfo();updHUD();}\nfunction updateLInfo(){const e=$('lInfo');const L=ST.lights.find(x=>x.id===SELL);if(!e||!L)return;const g=geo();const lp=lightPos(L,g),tp=aimPt(L,g);const d=vlen(vsub(lp,tp));const md=modOf(L);const soft=Math.max(md.w,md.h)\/d;const b=standBase(L,g);\n e.innerHTML='C\u00e1ch \u0111i\u1ec3m chi\u1ebfu <b>'+d.toFixed(2)+' m<\/b>, \u0111\u1ed9 m\u1ec1m '+softTxt(soft)+'.<br>D\u00e1n d\u1ea5u X ch\u00e2n \u0111\u00e8n: '+wallCoords(b)+'.'+(L.boom?'<br>Tay boom v\u01b0\u01a1n '+Math.hypot(lp.x-b.x,lp.z-b.z).toFixed(2)+' m.':'');}\nlet METER_MINI=false;\nfunction updateMeter(){const M=meter();const c=ST.cam;const box=$('meter');if(!box)return;const ev=M.ev;const cls=Math.abs(ev)<0.34?['#12301f','#8ff0b8','\u0110\u00fang s\u00e1ng v\u1edbi f\/'+c.N]:ev>0?['#3a2412','#ffc98f','D\u01b0 '+ev.toFixed(1)+' EV v\u1edbi f\/'+c.N]:['#141d3a','#9fb8ff','Thi\u1ebfu '+(-ev).toFixed(1)+' EV v\u1edbi f\/'+c.N];\n let rows='';const inc=[];ST.lights.forEach((L,i)=>{const p=M.per[i];if(!p)return;inc.push([L,p.inc]);rows+='<div><span><span class=\"d\" style=\"background:'+LCOLS[i%5]+'\"><\/span>'+L.name+'<\/span><span>'+fmtLux(p.inc)+' lx \u00b7 '+fmtN(Math.sqrt(p.inc*c.t*c.ISO\/250))+'<\/span><\/div>';});\n rows+='<div><span>M\u00f4i tr\u01b0\u1eddng + h\u1eaft t\u01b0\u1eddng<\/span><span>'+fmtLux(M.amb)+' lx<\/span><\/div>';\n const keys=inc.filter(x=>x[0].role==='key'||x[0].role==='fill');keys.sort((a,b)=>b[1]-a[1]);let ratio='';if(keys.length>=2&&keys[1][1]>1){const r=keys[0][1]\/keys[1][1];ratio='<div><span>T\u1ec9 l\u1ec7 '+keys[0][0].name+' : '+keys[1][0].name+'<\/span><span>'+r.toFixed(1)+' : 1 ('+Math.log2(r).toFixed(1)+' stop)<\/span><\/div>';}\n let grp='';const W=warnings();if(M.grp){grp='<div><span>Ch\u00eanh s\u00e1ng trong nh\u00f3m<\/span><span>'+M.grp.spread.toFixed(1)+' stop<\/span><\/div>';if(M.grp.spread>1)W.push('Ng\u01b0\u1eddi r\u00eca v\u00e0 ng\u01b0\u1eddi gi\u1eefa l\u1ec7ch '+M.grp.spread.toFixed(1)+' stop \u2014 \u0111\u1ea9y \u0111\u00e8n xa h\u01a1n, n\u00e2ng cao, d\u00f9ng d\u00f9 ho\u1eb7c softbox l\u1edbn h\u01a1n');}\n box.className='meter'+(METER_MINI?' mini':'');\n box.innerHTML='<div class=\"mt\" id=\"mtHead\" title=\"B\u1ea5m \u0111\u1ec3 thu g\u1ecdn ho\u1eb7c m\u1edf\"><span>M\u00e1y \u0111o s\u00e1ng, '+(M.grp?'trung b\u00ecnh '+M.grp.n+' ng\u01b0\u1eddi':'t\u1ea1i m\u1eb7t')+'<\/span><span>ISO '+c.ISO+' \u00b7 '+fmtT(c.t)+'<\/span><\/div><div class=\"big\">'+fmtN(M.Nrec)+'<\/div><div class=\"sub\">kh\u1ea9u \u0111\u1ec1 xu\u1ea5t \u00b7 '+fmtLux(M.tot)+' lux t\u1edbi m\u1eb7t<\/div><div class=\"ev\" style=\"background:'+cls[0]+';color:'+cls[1]+'\">'+cls[2]+'<\/div><div class=\"rows\">'+rows+ratio+grp+'<\/div>'+(W.length?'<div class=\"warn\">'+W.join('<br>')+'<\/div>':'')+'<button id=\"btnUseN\">\u0110\u1eb7t kh\u1ea9u theo \u0111\u1ec1 xu\u1ea5t<\/button>';\n $('mtHead').onclick=()=>{METER_MINI=!METER_MINI;updateMeter();};\n $('btnUseN').onclick=()=>{let b=SAP[0];SAP.forEach(a=>{if(Math.abs(Math.log2(a\/M.Nrec))<Math.abs(Math.log2(b\/M.Nrec)))b=a;});ST.cam.N=b;buildLeft();changed();toast('\u0110\u00e3 \u0111\u1eb7t kh\u1ea9u f\/'+b);};\n updateLInfo();updHUD();updateMissions(M);updPip();}\n\/* ----- plan (top-down) ----- *\/\nfunction planMap(cv){const r=ST.room;const W=cv.width,H=cv.height,pad=W*0.08;const sc=Math.min((W-pad*2)\/r.w,(H-pad*2)\/r.l);return {sc,tx:x=>W\/2+x*sc,tz:z=>H\/2+z*sc,ix:px=>(px-W\/2)\/sc,iz:py=>(py-H\/2)\/sc};}\nfunction drawX(ctx,x,y,s,col){ctx.strokeStyle=col;ctx.lineWidth=Math.max(2,s*0.35);ctx.beginPath();ctx.moveTo(x-s,y-s);ctx.lineTo(x+s,y+s);ctx.moveTo(x+s,y-s);ctx.lineTo(x-s,y+s);ctx.stroke();}\nfunction drawPlan(cv,big){const ctx=ctx2d(cv);if(!ctx)return;const W=cv.width,H=cv.height;const r=ST.room,g=geo();const M=planMap(cv);const k=W\/500;const V2=ST.view||{};\n ctx.fillStyle='#0b101d';ctx.fillRect(0,0,W,H);const x0=M.tx(-r.w\/2),z0=M.tz(-r.l\/2),rw=r.w*M.sc,rl=r.l*M.sc;ctx.fillStyle='#141c30';ctx.fillRect(x0,z0,rw,rl);\n ctx.strokeStyle='#1f2a45';ctx.lineWidth=1;ctx.beginPath();for(let x=Math.ceil(-r.w\/2);x<=r.w\/2;x++){ctx.moveTo(M.tx(x),z0);ctx.lineTo(M.tx(x),z0+rl);}for(let z=Math.ceil(-r.l\/2);z<=r.l\/2;z++){ctx.moveTo(x0,M.tz(z));ctx.lineTo(x0+rw,M.tz(z));}ctx.stroke();\n ctx.strokeStyle='#5d6985';ctx.lineWidth=2*k;ctx.strokeRect(x0,z0,rw,rl);\n ctx.fillStyle='#8e9ab3';ctx.font='600 '+(13*k)+'px \"Be Vietnam Pro\"';ctx.textAlign='center';ctx.fillText(r.w.toFixed(1)+' m',W\/2,z0-7*k);ctx.save();ctx.translate(x0-8*k,H\/2);ctx.rotate(-Math.PI\/2);ctx.fillText(r.l.toFixed(1)+' m',0,0);ctx.restore();\n ctx.fillStyle='#5d6985';ctx.font='500 '+(10*k)+'px \"Be Vietnam Pro\"';ctx.fillText('t\u01b0\u1eddng sau',W\/2,z0+13*k);ctx.fillText('tr\u00e1i',x0+14*k,H\/2);ctx.fillText('ph\u1ea3i',x0+rw-14*k,H\/2);\n if(ST.bd.on){const bw=bdW();const fl=0.45+bdFloor();ctx.fillStyle=ST.bd.color;ctx.globalAlpha=.22;ctx.fillRect(M.tx(g.bx-bw\/2),M.tz(g.bz),bw*M.sc,fl*M.sc);ctx.globalAlpha=1;[['#5d6985',10*k],[ST.bd.color,6*k]].forEach(s=>{ctx.strokeStyle=s[0];ctx.lineWidth=s[1];ctx.lineCap='round';ctx.beginPath();ctx.moveTo(M.tx(g.bx-bw\/2),M.tz(g.bz));ctx.lineTo(M.tx(g.bx+bw\/2),M.tz(g.bz));ctx.stroke();});ctx.lineCap='butt';}\n const c=ST.cam;const hf=Math.atan(sensorH()\/2\/c.focal);const AIMp=camAim(g);const yaw=Math.atan2(AIMp.x-g.cam.x,AIMp.z-g.cam.z);const far=camDist(g)*1.7+0.5;const cz=g.cam.z;ctx.fillStyle='rgba(122,162,255,.08)';ctx.strokeStyle='rgba(122,162,255,.4)';ctx.lineWidth=1;ctx.beginPath();ctx.moveTo(M.tx(g.cam.x),M.tz(cz));ctx.lineTo(M.tx(g.cam.x+Math.sin(yaw-hf)*far),M.tz(cz+Math.cos(yaw-hf)*far));ctx.lineTo(M.tx(g.cam.x+Math.sin(yaw+hf)*far),M.tz(cz+Math.cos(yaw+hf)*far));ctx.closePath();ctx.fill();ctx.stroke();\n ST.lights.forEach((L,i)=>{const lp=lightPos(L,g),tp=aimPt(L,g);const col=L.on?LCOLS[i%5]:'#3a4460';const md=modOf(L);const ang=Math.atan2(tp.x-lp.x,tp.z-lp.z);const b=standBase(L,g);\n  if(L.boom){ctx.strokeStyle='#6b7690';ctx.lineWidth=2.5*k;ctx.beginPath();ctx.moveTo(M.tx(b.x),M.tz(b.z));ctx.lineTo(M.tx(lp.x),M.tz(lp.z));ctx.stroke();}\n  if(V2.marks)drawX(ctx,M.tx(b.x),M.tz(b.z),6*k,L.on?'#ffc53d':'#6b6040');\n  ctx.setLineDash([5*k,5*k]);ctx.strokeStyle=L.on&&L.gel?L.gel:col;ctx.globalAlpha=.55;ctx.lineWidth=1.5*k;ctx.beginPath();ctx.moveTo(M.tx(lp.x),M.tz(lp.z));ctx.lineTo(M.tx(tp.x),M.tz(tp.z));ctx.stroke();ctx.setLineDash([]);ctx.globalAlpha=1;\n  ctx.save();ctx.translate(M.tx(lp.x),M.tz(lp.z));ctx.rotate(-ang);const pw=Math.max(md.w*M.sc,10*k),ph=Math.max(0.14*M.sc,6*k);ctx.fillStyle=col;ctx.fillRect(-pw\/2,-ph\/2,pw,ph);if(L.id===SELL){ctx.strokeStyle='#fff';ctx.lineWidth=2*k;ctx.strokeRect(-pw\/2-3*k,-ph\/2-3*k,pw+6*k,ph+6*k);}ctx.restore();\n  ctx.fillStyle='#e9eef7';ctx.font='700 '+(12*k)+'px \"Be Vietnam Pro\"';ctx.textAlign='center';ctx.fillText(L.name,M.tx(lp.x),M.tz(lp.z)-12*k);\n  if(big||L.id===SELL){ctx.fillStyle='#cfd8ea';ctx.font='600 '+(12*k)+'px \"Barlow Condensed\"';ctx.fillText(vlen(vsub(lp,tp)).toFixed(2)+' m \u00b7 cao '+L.height.toFixed(2),M.tx(lp.x),M.tz(lp.z)+20*k);}});\n const many=g.faces.length>1;g.faces.forEach(f=>{ctx.fillStyle='#d9b59c';ctx.beginPath();ctx.arc(M.tx(f.x),M.tz(f.z),Math.max(0.2*M.sc,(many?3:6)*k),0,7);ctx.fill();});\n if(!many){ctx.strokeStyle='#fff';ctx.lineWidth=2*k;const fr=rad(ST.subj.rot||0);ctx.beginPath();ctx.moveTo(M.tx(g.sx),M.tz(g.sz));ctx.lineTo(M.tx(g.sx+Math.sin(fr)*0.35),M.tz(g.sz+Math.cos(fr)*0.35));ctx.stroke();}\n if(V2.marks){drawX(ctx,M.tx(g.sx),M.tz(g.sz),4*k,'#ffffff');drawX(ctx,M.tx(g.cam.x),M.tz(cz),5*k,'#7aa2ff');}\n ctx.fillStyle='#7aa2ff';ctx.save();ctx.translate(M.tx(g.cam.x),M.tz(cz));ctx.rotate(Math.PI-yaw);ctx.beginPath();ctx.moveTo(0,-10*k);ctx.lineTo(-9*k,8*k);ctx.lineTo(9*k,8*k);ctx.closePath();ctx.fill();ctx.restore();\n ctx.fillStyle='#8e9ab3';ctx.font='600 '+(11*k)+'px \"Be Vietnam Pro\"';ctx.textAlign='center';ctx.fillText('m\u00e1y '+camDist(g).toFixed(1)+' m',M.tx(g.cam.x),M.tz(cz)+22*k);ctx.textAlign='left';}\nlet PDRAG=null;\nfunction planEvents(){const cv=$('plan');const pt=e=>{const r=cv.getBoundingClientRect();return {x:(e.clientX-r.left)*cv.width\/r.width,y:(e.clientY-r.top)*cv.height\/r.height};};\n cv.addEventListener('pointerdown',e=>{const p=pt(e);const M=planMap(cv);const g=geo();let hit=null,best=26*(cv.width\/500);\n  ST.lights.forEach(L=>{const lp=lightPos(L,g);const d=Math.hypot(M.tx(lp.x)-p.x,M.tz(lp.z)-p.y);if(d<best){best=d;hit={t:'light',L};}});\n  const ds=Math.hypot(M.tx(g.sx)-p.x,M.tz(g.sz)-p.y);if(ds<best){best=ds;hit={t:'subj'};}const dc=Math.hypot(M.tx(g.cam.x)-p.x,M.tz(g.cam.z)-p.y);if(dc<best){hit={t:'cam'};}\n  if(!hit&&ST.bd.on){const bw=bdW();if(Math.abs(p.y-M.tz(g.bz))<14*(cv.width\/500)&&p.x>M.tx(g.bx-bw\/2)-8&&p.x<M.tx(g.bx+bw\/2)+8)hit={t:'bd',off:M.ix(p.x)-g.bx};}\n  if(hit){PDRAG=hit;if(hit.t==='light'){SELL=hit.L.id;buildRight();DIRTY=true;}cv.setPointerCapture&&cv.setPointerCapture(e.pointerId);e.preventDefault();}});\n cv.addEventListener('pointermove',e=>{if(!PDRAG)return;const p=pt(e);const M=planMap(cv);const x=M.ix(p.x),z=M.iz(p.y);const g=geo();const r=ST.room;\n  if(PDRAG.t==='light'){const L=PDRAG.L;const dx=x-g.sx,dz=z-g.sz;L.az=Math.round(Math.atan2(dx,dz)*180\/Math.PI);L.dist=Math.round(clamp(Math.hypot(dx,dz),0.3,8)*20)\/20;}\n  else if(PDRAG.t==='subj'){ST.subj.x=Math.round(clamp(x,-r.w\/2+0.3,r.w\/2-0.3)*20)\/20;ST.subj.bd=Math.round(clamp(z-g.bz,0.4,r.l-ST.bd.gap-0.5)*20)\/20;}\n  else if(PDRAG.t==='bd'){moveBd(Math.round((x-PDRAG.off)*20)\/20,Math.round((z+r.l\/2)*20)\/20);}\n  else{const dx=x-g.sx,dz=z-g.sz;ST.cam.dist=Math.round(clamp(Math.hypot(dx,dz),0.5,12)*20)\/20;ST.cam.az=Math.round(Math.atan2(dx,dz)*180\/Math.PI);}\n  DIRTY=true;drawPlan(cv);updateMeter();saveSoon();});\n const up=()=>{if(PDRAG){PDRAG=null;buildLeft();buildRight();histSave();}};cv.addEventListener('pointerup',up);cv.addEventListener('pointercancel',up);}\n\/* ----- presets ----- *\/\nconst PRESET_DEF={\n rembrandt:{bd:'#8e9196',L:[['key',{mod:'octa',size:1,power:300,az:45,dist:1.6,height:2.15}],['fill',{mod:'softbox',size:0,power:50,az:-40,dist:2.6,height:1.6}]]},\n loop:{bd:'#8e9196',L:[['key',{mod:'octa',size:1,power:300,az:30,dist:1.5,height:2.0}],['fill',{mod:'softbox',size:0,power:80,az:-35,dist:2.5,height:1.6}]]},\n butterfly:{bd:'#eeeeee',L:[['key',{mod:'dish',size:1,power:250,az:0,dist:1.2,height:2.25}],['fill',{name:'Fill d\u01b0\u1edbi',mod:'strip',size:0,power:60,az:0,dist:1.0,height:0.9}]]},\n split:{bd:'#141416',cam:{N:4},L:[['key',{mod:'strip',size:0,power:250,az:90,dist:1.1,height:1.7}]]},\n clamshell:{bd:'#eeeeee',L:[['key',{name:'Key tr\u00ean',mod:'octa',size:0,power:250,az:0,dist:1.2,height:2.1}],['fill',{name:'Fill d\u01b0\u1edbi',mod:'softbox',size:0,power:90,az:0,dist:1.0,height:0.95}]]},\n three:{bd:'#1d2b4f',L:[['key',{mod:'softbox',size:1,power:300,az:40,dist:1.8,height:2.0}],['fill',{mod:'octa',size:0,power:90,az:-45,dist:2.6,height:1.6}],['rim',{az:-145}],['hair',{}],['bg',{}]]},\n boom:{bd:'#141416',wall:'black',cam:{N:4},L:[['top',{power:260}],['rim',{az:150,power:160}],['fill',{name:'Fill d\u01b0\u1edbi',mod:'strip',size:0,power:40,az:0,dist:1.1,height:0.9}]]},\n highkey:{bd:'#eeeeee',wall:'white',cam:{N:8},L:[['key',{mod:'octa',size:2,power:400,az:0,dist:2.2,height:2.0}],['bg',{name:'N\u1ec1n tr\u00e1i',power:400,az:145,dist:1.3,height:1.2}],['bg',{name:'N\u1ec1n ph\u1ea3i',power:400,az:-145,dist:1.3,height:1.2}]]},\n lowkey:{bd:'#141416',wall:'black',cam:{N:4},L:[['key',{mod:'strip',size:0,power:220,az:55,dist:1.2,height:1.9,grid:true}],['rim',{power:180,az:-140,dist:1.3,height:1.9}]]},\n group:{bd:'#8e9196',subj:'group',count:12,sbd:2.6,cam:{N:8,dist:3.3,focal:35,portrait:false,height:1.7},L:[['key',{name:'Key tr\u00e1i',mod:'umb',size:1,power:600,az:35,dist:3.1,height:2.6}],['key',{name:'Key ph\u1ea3i',mod:'umb',size:1,power:600,az:-35,dist:3.1,height:2.6}],['bg',{power:300,dist:1.1}]]},\n colorbg:{bd:'#4a4d52',wall:'black',cam:{N:4},L:[['key',{mod:'octa',size:1,power:280,az:40,dist:1.6,height:2.05}],['bg',{name:'N\u1ec1n xanh',mod:'bare',grid:true,power:450,az:155,dist:1.1,height:0.7,gel:'#2f6bff',bgX:-0.55,bgY:1.7}],['bg',{name:'N\u1ec1n h\u1ed3ng',mod:'bare',grid:true,power:450,az:-155,dist:1.1,height:0.7,gel:'#ff4fb0',bgX:0.6,bgY:1.05}],['rim',{az:-145,power:150}]]},\n product:{bd:'#eeeeee',subj:'product',cam:{N:8},L:[['key',{mod:'softbox',size:3,power:350,az:70,dist:1.3,height:1.4,aim:'body'}],['fill',{mod:'softbox',size:0,power:100,az:-70,dist:1.6,height:1.2,aim:'body'}],['top',{mod:'strip',size:1,power:150,dist:0.3,height:2.2,aim:'body'}]]}};\nfunction applyPreset(k){const p=PRESET_DEF[k];if(!p)return;ST.bd.on=true;ST.bd.color=p.bd;ST.subj.type=p.subj||'person';ST.subj.bd=p.sbd||1.8;ST.subj.x=0;ST.subj.rot=0;if(p.count)ST.subj.count=p.count;if(p.wall)ST.room.wall=p.wall;ST.room.ambient=10;Object.assign(ST.cam,{dist:3.2,height:1.55,focal:85,portrait:true,N:5.6,t:1\/125,ISO:400,az:0,tilt:0,pan:0},p.cam||{});ST.cam.aspect=ST.cam.portrait?'2:3':'3:2';\n ST.lights=p.L.map(e=>{const role=e[0];return mkLight(Object.assign({name:ROLE_NAME[role],role},ROLES[role].o,e[1]));});\n const seen={};ST.lights.forEach(L=>{if(seen[L.name]){seen[L.name]++;L.name=L.name+' '+seen[L.name];}else seen[L.name]=1;});\n SELL=ST.lights[0].id;buildLeft();buildRight();changed();syncOrientBtn();toast('\u0110\u00e3 \u00e1p setup '+SETUP_TXT[k][0]);}\nfunction openPreset(k){setTab('studio');applyPreset(k);}\n\n\/* ----- THREE scene ----- *\/\nlet S3=null,DIRTY=true,MODE='orbit';\nfunction mat(hex,rough,metal){return new THREE.MeshStandardMaterial({color:new THREE.Color(hex).convertSRGBToLinear(),roughness:rough==null?.8:rough,metalness:metal||0});}\nfunction disposeObj(o){o.traverse(x=>{if(x.userData&&x.userData.shared)return;if(x.geometry)x.geometry.dispose();if(x.material){(Array.isArray(x.material)?x.material:[x.material]).forEach(m=>m.dispose());}});}\nfunction initStudio(){buildLeft();buildRight();drawPlan($('plan'));updateMeter();syncViewBtns();if(S3){resize3d();return;}\n if(typeof THREE==='undefined'||!THREE.WebGLRenderer){$('noGL').style.display='flex';return;}\n const host=$('view3d');let renderer;try{renderer=new THREE.WebGLRenderer({antialias:true,preserveDrawingBuffer:true});}catch(e){$('noGL').style.display='flex';$('noGL').textContent='M\u00e1y n\u00e0y kh\u00f4ng h\u1ed7 tr\u1ee3 WebGL \u2014 th\u1eed Chrome ho\u1eb7c Edge b\u1ea3n m\u1edbi.';return;}\n renderer.setPixelRatio(Math.min(2,window.devicePixelRatio||1));renderer.physicallyCorrectLights=true;renderer.outputEncoding=THREE.sRGBEncoding;renderer.toneMapping=THREE.ACESFilmicToneMapping;renderer.shadowMap.enabled=true;renderer.shadowMap.type=THREE.PCFShadowMap;host.appendChild(renderer.domElement);\n if(THREE.RectAreaLightUniformsLib)THREE.RectAreaLightUniformsLib.init();\n const scene=new THREE.Scene();scene.background=new THREE.Color(0x05070d);\n const cam=new THREE.PerspectiveCamera(45,1,0.05,300);const pov=new THREE.PerspectiveCamera(30,1,0.05,300);\n const controls=THREE.OrbitControls?new THREE.OrbitControls(cam,renderer.domElement):null;if(controls){controls.enableDamping=true;controls.maxPolarAngle=Math.PI*0.495;}\n const hemi=new THREE.HemisphereLight(0xffffff,0x444444,10);scene.add(hemi);\n S3={renderer,scene,cam,pov,controls,hemi,lights:{},pickables:[]};buildCamMark();initHead();S3.clock=THREE.Clock?new THREE.Clock():null;\n const rg=new THREE.Group();const rmat=new THREE.MeshBasicMaterial({color:0xffb259,transparent:true,opacity:.6,side:THREE.DoubleSide,depthWrite:false});const rm=new THREE.Mesh(new THREE.RingGeometry(.56,.6,72),rmat);rm.rotation.x=-Math.PI\/2;rg.add(rm);const hitm=new THREE.Mesh(new THREE.RingGeometry(.47,.7,48),new THREE.MeshBasicMaterial({visible:false,side:THREE.DoubleSide}));hitm.rotation.x=-Math.PI\/2;rg.add(hitm);const knob=new THREE.Mesh(new THREE.SphereGeometry(.06,18,12),new THREE.MeshBasicMaterial({color:0xffb259}));rg.add(knob);const tip=new THREE.Mesh(new THREE.ConeGeometry(.045,.12,14),new THREE.MeshBasicMaterial({color:0xffb259}));tip.rotation.x=Math.PI\/2;rg.add(tip);rg.userData.knob=knob;rg.userData.tip=tip;rg.userData.pick={t:'rot'};scene.add(rg);S3.rotRing=rg;\n S3.subjX=xMark(0xffffff);S3.camX=xMark(0x7aa2ff);scene.add(S3.subjX);scene.add(S3.camX);\n S3.dimBd=dashLine(0x7aa2ff);S3.dimCam=dashLine(0x7aa2ff);scene.add(S3.dimBd);scene.add(S3.dimCam);\n resetView();\n if(window.ResizeObserver){new ResizeObserver(resize3d).observe(host);}else window.addEventListener('resize',resize3d);\n initPicking();initPip();resize3d();loop();setTimeout(preloadChars,2500);}\nfunction resize3d(){if(typeof updPip==='function')setTimeout(updPip);if(!S3)return;const h=$('view3d');const w=Math.max(10,h.clientWidth),hh=Math.max(10,h.clientHeight);S3.renderer.setSize(w,hh,false);S3.cam.aspect=w\/hh;S3.cam.updateProjectionMatrix();layoutPOV();}\nfunction frameRect(){const h=$('view3d');const W=h.clientWidth||800,H=h.clientHeight||600;const ar=frameAR();let fw=W-60,fh=fw\/ar;if(fh>H-100){fh=H-100;fw=fh*ar;}return {x:(W-fw)\/2,y:(H-fh)\/2+10,w:fw,h:fh,W,H};}\nfunction layoutPOV(){const f=$('povFrame');if(!S3)return;if(MODE!=='pov'){f.style.display='none';return;}const r=frameRect();f.style.display='block';f.style.left=r.x+'px';f.style.top=r.y+'px';f.style.width=r.w+'px';f.style.height=r.h+'px';\n f.innerHTML='<div class=\"g\" style=\"left:33.33%;top:0;bottom:0;width:1px\"><\/div><div class=\"g\" style=\"left:66.66%;top:0;bottom:0;width:1px\"><\/div><div class=\"g\" style=\"top:33.33%;left:0;right:0;height:1px\"><\/div><div class=\"g\" style=\"top:66.66%;left:0;right:0;height:1px\"><\/div>';\n const sv=sensorV();const vf=2*Math.atan(sv\/(2*ST.cam.focal));const vv=2*Math.atan(Math.tan(vf\/2)*(r.H\/r.h));S3.pov.fov=vv*180\/Math.PI;S3.pov.aspect=r.W\/r.H;S3.pov.updateProjectionMatrix();}\nfunction flipAspect(){const a=ST.cam.aspect||'2:3';const p=a.split(':');setAspect(p[1]+':'+p[0]);}\nfunction syncOrientBtn(){const b=$('btnOrient');if(b)b.textContent=(typeof frameAR==='function'&&ST.cam.aspect?frameAR()<1:ST.cam.portrait)?'M\u00e1y d\u1ecdc':'M\u00e1y ngang';layoutPOV();}\nfunction canvasTex(w,h,draw,rx,ry){const c=document.createElement('canvas');c.width=w;c.height=h;const x=ctx2d(c);if(!x)return null;try{draw(x,w,h);}catch(e){return null;}const t=new THREE.CanvasTexture(c);t.wrapS=t.wrapT=THREE.RepeatWrapping;t.repeat.set(rx,ry);t.encoding=THREE.sRGBEncoding;t.anisotropy=4;return t;}\nfunction seeded(s){return ()=>{s=(s*9301+49297)%233280;return s\/233280;};}\nfunction brickDraw(x,w,h){x.fillStyle='#4f4038';x.fillRect(0,0,w,h);const r=seeded(11);const bh=32,bw=96;const tones=[[138,74,50],[150,84,58],[122,64,44],[160,96,66],[112,60,42]];for(let row=0;row<h\/bh;row++){const off=row%2?bw\/2:0;for(let col=-1;col<w\/bw+1;col++){const t=tones[Math.floor(r()*tones.length)];const k=.82+r()*.3;x.fillStyle='rgb('+Math.round(t[0]*k)+','+Math.round(t[1]*k)+','+Math.round(t[2]*k)+')';x.fillRect(col*bw+off+3,row*bh+3,bw-6,bh-6);}}}\nfunction concreteDraw(x,w,h){x.fillStyle='#5d5f63';x.fillRect(0,0,w,h);const r=seeded(5);for(let i=0;i<3200;i++){const v=78+Math.floor(r()*44);x.fillStyle='rgba('+v+','+v+','+(v+3)+','+(0.04+r()*0.08).toFixed(3)+')';const s=1+r()*7;x.fillRect(r()*w,r()*h,s,s);}}\nfunction buildRoom(){const r=ST.room;if(S3.room){S3.scene.remove(S3.room);disposeObj(S3.room);}const g=new THREE.Group();let wm;\n if(r.wall==='brick'){const t=canvasTex(512,512,brickDraw,Math.max(r.w,r.l)\/1.3,r.h\/1.05);wm=t?new THREE.MeshStandardMaterial({map:t,roughness:.95}):mat(WALLS.brick.c,.95);}else wm=mat(WALLS[r.wall].c,.92);\n wm.side=THREE.BackSide;const box=new THREE.Mesh(new THREE.BoxGeometry(r.w,r.h,r.l),wm);box.position.y=r.h\/2;box.receiveShadow=true;g.add(box);\n const ft=canvasTex(512,512,concreteDraw,r.w\/2.5,r.l\/2.5);const fm=ft?new THREE.MeshStandardMaterial({map:ft,roughness:.82}):mat('#55575b',.9);const fl=new THREE.Mesh(new THREE.PlaneGeometry(r.w,r.l),fm);fl.rotation.x=-Math.PI\/2;fl.position.y=0.002;fl.receiveShadow=true;g.add(fl);\n const pts=[];for(let x=Math.ceil(-r.w\/2);x<=r.w\/2;x++)pts.push(x,0.005,-r.l\/2,x,0.005,r.l\/2);for(let z=Math.ceil(-r.l\/2);z<=r.l\/2;z++)pts.push(-r.w\/2,0.005,z,r.w\/2,0.005,z);\n const lg=new THREE.BufferGeometry();lg.setAttribute('position',new THREE.Float32BufferAttribute(pts,3));g.add(new THREE.LineSegments(lg,new THREE.LineBasicMaterial({color:0x9aa3b5,transparent:true,opacity:.12})));\n S3.scene.add(g);S3.room=g;}\nfunction sweepGeo(width,height,radius,floorLen){const prof=[[0,height],[0,radius]];const segs=12;for(let i=1;i<=segs;i++){const a=(Math.PI\/2)*(i\/segs);prof.push([radius-Math.cos(a)*radius,radius-Math.sin(a)*radius]);}prof.push([radius+floorLen,0]);\n const pos=[],idx=[],uv=[];let tot=0;const cum=[0];for(let i=1;i<prof.length;i++){tot+=Math.hypot(prof[i][0]-prof[i-1][0],prof[i][1]-prof[i-1][1]);cum.push(tot);}prof.forEach((p,i)=>{pos.push(-width\/2,p[1]+0.004,p[0],width\/2,p[1]+0.004,p[0]);const v=1-cum[i]\/tot;uv.push(0,v,1,v);});for(let i=0;i<prof.length-1;i++){const a=i*2,b=a+1,c=a+2,d=a+3;idx.push(a,b,c,b,d,c);}\n const g=new THREE.BufferGeometry();g.setAttribute('position',new THREE.Float32BufferAttribute(pos,3));g.setAttribute('uv',new THREE.Float32BufferAttribute(uv,2));g.setIndex(idx);g.computeVertexNormals();return g;}\nfunction buildBackdrop(){if(S3.bd){S3.scene.remove(S3.bd);disposeObj(S3.bd);S3.bd=null;}if(!ST.bd.on)return;const r=ST.room,g=geo();const grp=new THREE.Group();const bw=bdW(),bh=Math.min(2.7,r.h-0.3);\n let m;if(ST.bd.tex){const t=canvasTex(512,512,(x,w,h)=>muslinDraw(x,w,h,ST.bd.color),1,1);m=t?new THREE.MeshStandardMaterial({map:t,roughness:.97}):mat(ST.bd.color,.95);}else m=mat(ST.bd.color,.95);m.side=THREE.DoubleSide;const sw=new THREE.Mesh(sweepGeo(bw,bh,0.45,bdFloor()),m);sw.receiveShadow=true;grp.add(sw);\n const pm=mat('#2a2c30',.5,.6);[-1,1].forEach(s=>{const x0=s*(bw\/2+.06);const p=new THREE.Mesh(new THREE.CylinderGeometry(.018,.018,bh+.1,8),pm);p.position.set(x0,(bh+.1)\/2,-.05);grp.add(p);for(let i=0;i<3;i++){const a=i*2.094+.52;grp.add(rod([x0,.4,-.05],[x0+Math.sin(a)*.42,.012,-.05+Math.cos(a)*.42],.009,pm,6));}});const bar=new THREE.Mesh(new THREE.CylinderGeometry(.03,.03,bw+.2,10),pm);bar.rotation.z=Math.PI\/2;bar.position.set(0,bh+.05,-.05);grp.add(bar);\n grp.position.set(g.bx,0,g.bz);grp.userData.pick={t:'bd'};S3.scene.add(grp);S3.bd=grp;}\nfunction v3(a){return Array.isArray(a)?new THREE.Vector3(a[0],a[1],a[2]):new THREE.Vector3(a.x,a.y,a.z);}\nfunction setRod(o,a,b){const A=v3(a),B=v3(b);const d=B.clone().sub(A);const len=Math.max(1e-4,d.length());o.scale.set(1,len,1);o.position.copy(A).add(B).multiplyScalar(.5);o.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0),d.divideScalar(len));}\nfunction rod(a,b,r,m,seg){const o=new THREE.Mesh(new THREE.CylinderGeometry(r,r,1,seg||8),m);setRod(o,a,b);return o;}\nfunction limb(a,b,r1,r2,m,seg){const A=v3(a),B=v3(b);const L=Math.max(1e-3,A.distanceTo(B));const pts=[],n=5;for(let i=0;i<=n;i++){const t=-Math.PI\/2+i\/n*Math.PI\/2;pts.push(new THREE.Vector2(Math.max(1e-4,r1*Math.cos(t)),r1*Math.sin(t)));}for(let i=0;i<=n;i++){const t=i\/n*Math.PI\/2;pts.push(new THREE.Vector2(Math.max(1e-4,r2*Math.cos(t)),L+r2*Math.sin(t)));}const o=new THREE.Mesh(new THREE.LatheGeometry(pts,seg||14),m);o.position.copy(A);o.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0),B.clone().sub(A).normalize());return o;}\nfunction personMesh(lod,shirt,pants){const g=new THREE.Group();const skin=S3.mSkin,hair=S3.mHair,shoe=S3.mShoe;const sg=lod?8:16;const add=o=>{g.add(o);return o;};const P=a=>a.map(p=>new THREE.Vector2(p[0],p[1]));\n const tor=new THREE.Mesh(new THREE.LatheGeometry(P([[0.001,1.0],[.155,1.0],[.148,1.07],[.152,1.15],[.17,1.24],[.182,1.32],[.186,1.39],[.17,1.45],[.12,1.49],[.06,1.515],[0.001,1.52]]),lod?12:28),shirt);tor.scale.set(1,1,.62);add(tor);\n const pel=new THREE.Mesh(new THREE.LatheGeometry(P([[0.001,.83],[.12,.84],[.165,.9],[.172,.96],[.158,1.02],[0.001,1.03]]),lod?12:28),pants);pel.scale.set(1,1,.7);add(pel);\n [-1,1].forEach(s=>{const hip=[s*.095,.9,0],knee=[s*.1,.5,.015],ank=[s*.105,.09,-.005];add(limb(hip,knee,.072,.054,pants,sg));add(limb(knee,ank,.05,.036,pants,sg));add(limb([s*.105,.05,-.05],[s*.108,.045,.14],.045,.04,shoe,sg));\n  const sh=[s*.195,1.43,0],el=[s*.235,1.16,-.03],wr=[s*.24,.93,.04];add(limb(sh,el,.05,.042,shirt,sg));add(limb(el,wr,.04,.032,shirt,sg));const hand=add(limb(wr,[s*.235,.84,.065],.028,.022,skin,sg));hand.scale.x=.75;\n  const sb=new THREE.Mesh(new THREE.SphereGeometry(.058,sg,sg-2),shirt);sb.position.set(s*.19,1.425,0);add(sb);});\n add(limb([0,1.48,0],[0,1.6,.01],.048,.044,skin,sg));\n if(S3.headGeo){const hm=new THREE.Mesh(S3.headGeo,S3.headMat);hm.userData.shared=true;add(hm);if(!lod){const col=new THREE.Mesh(new THREE.TorusGeometry(.058,.012,8,20),shirt);col.rotation.x=Math.PI\/2;col.position.set(0,1.495,.005);col.scale.set(1,.8,1);add(col);}}\n else{const head=new THREE.Mesh(new THREE.SphereGeometry(.1,lod?12:28,lod?10:22),skin);head.position.set(0,1.672,.005);head.scale.set(.86,1.1,.98);add(head);\n const jaw=new THREE.Mesh(new THREE.SphereGeometry(.072,lod?10:20,lod?8:14),skin);jaw.position.set(0,1.598,.03);jaw.scale.set(.95,.78,.95);add(jaw);\n const nose=new THREE.Mesh(new THREE.ConeGeometry(.018,.05,lod?6:12),skin);nose.rotation.x=Math.PI\/2;nose.position.set(0,1.655,.108);nose.scale.set(1,1,.85);add(nose);\n if(!lod){const brow=new THREE.Mesh(new THREE.SphereGeometry(.085,20,10),skin);brow.position.set(0,1.705,.06);brow.scale.set(1,.22,.55);add(brow);\n  [-1,1].forEach(s=>{const ear=new THREE.Mesh(new THREE.SphereGeometry(.022,10,8),skin);ear.position.set(s*.086,1.665,-.005);ear.scale.set(.5,1,.8);add(ear);const eye=new THREE.Mesh(new THREE.SphereGeometry(.011,10,8),S3.mEye);eye.position.set(s*.032,1.676,.092);add(eye);});\n  const lips=new THREE.Mesh(new THREE.SphereGeometry(.022,12,8),S3.mLip);lips.position.set(0,1.607,.088);lips.scale.set(1.3,.45,.6);add(lips);\n  const col=new THREE.Mesh(new THREE.TorusGeometry(.058,.012,8,20),shirt);col.rotation.x=Math.PI\/2;col.position.set(0,1.495,.005);col.scale.set(1,.8,1);add(col);}\n const hc=new THREE.Mesh(new THREE.SphereGeometry(.108,lod?12:28,lod?8:16,0,Math.PI*2,0,Math.PI*.56),hair);hc.position.set(0,1.69,-.012);hc.scale.set(.92,1.12,1.04);add(hc);}return g;}\nfunction buildSubject(){if(S3.subj){S3.scene.remove(S3.subj);disposeObj(S3.subj);}const g=new THREE.Group();S3.mSkin=mat('#d2a48c',.58);S3.mHair=mat('#18130f',.7);S3.mShoe=mat('#111113',.45,.1);S3.mEye=mat('#1b1512',.25);S3.mLip=mat('#a8685f',.5);\n if(ST.subj.type==='product'){const add=(geom,m,x,y,z)=>{const o=new THREE.Mesh(geom,m);o.position.set(x,y,z);g.add(o);return o;};add(new THREE.BoxGeometry(.7,.04,.6),mat('#e2e2e2',.5),0,.73,0);[[-1,-1],[1,-1],[-1,1],[1,1]].forEach(p=>g.add(rod([p[0]*.31,0,p[1]*.26],[p[0]*.31,.71,p[1]*.26],.018,mat('#2a2c30',.4,.5),8)));\n  const glass=mat('#2a4d7a',.15,.1);add(new THREE.LatheGeometry([[0.001,0],[.05,0],[.052,.02],[.052,.17],[.045,.2],[.02,.235],[.019,.27],[0.001,.27]].map(p=>new THREE.Vector2(p[0],p[1])),40),glass,0,.75,0);add(new THREE.CylinderGeometry(.022,.022,.04,24),mat('#c9c9c9',.3,.7),0,1.035,0);}\n else{const lay=groupLayout();const shirts=['#2b2e36','#e8e6e1','#3a4458','#6b4a3a','#2f3d34','#1d2b4f'];const pantsC=['#1a1c20','#2c3038','#3a3226','#1f2430'];const many=lay.length>1;const sm=shirts.map(c=>mat(c,.85)),pm=pantsC.map(c=>mat(c,.8));\n  const chars=subjChars();MIXERS.length=0;lay.forEach((p,i)=>{let o=null;const c=chars.length?chars[i%chars.length]:null;if(c){const e=CHAR_CACHE[c.url];if(e&&e.status==='ok')o=charInstance(c,e,!many||i<6);else loadChar(c,()=>{if(S3)S3.ss=null;DIRTY=true;updateMeter();});}if(!o)o=personMesh(many,sm[many?i%sm.length:0],pm[many?(i*3)%pm.length:0]);o.position.set(p.x,0,p.z);o.scale.setScalar(p.h);g.add(o);});}\n g.traverse(o=>{if(o.isMesh){o.castShadow=true;o.receiveShadow=true;}});g.userData.pick={t:'subj'};S3.scene.add(g);S3.subj=g;}\nfunction buildCamMark(){const g=new THREE.Group();const body=mat('#1a1b1e',.45,.25),rub=mat('#0d0d0e',.85,0),al=mat('#8d939b',.4,.45),blk=mat('#17181b',.55,.2);const head=new THREE.Group();\n head.add(new THREE.Mesh(new THREE.BoxGeometry(.13,.088,.06),body));const grip=new THREE.Mesh(new THREE.BoxGeometry(.035,.08,.075),rub);grip.position.set(.052,-.004,.012);head.add(grip);const evf=new THREE.Mesh(new THREE.BoxGeometry(.05,.032,.055),body);evf.position.set(-.005,.058,-.004);head.add(evf);\n const dial=new THREE.Mesh(new THREE.CylinderGeometry(.012,.012,.008,14),blk);dial.position.set(.04,.048,-.005);head.add(dial);\n const mount=new THREE.Mesh(new THREE.CylinderGeometry(.03,.03,.012,24),al);mount.rotation.x=Math.PI\/2;mount.position.z=.036;head.add(mount);\n const lens=new THREE.Mesh(new THREE.CylinderGeometry(.034,.036,.1,28),blk);lens.rotation.x=Math.PI\/2;lens.position.z=.09;head.add(lens);\n [.07,.105].forEach(z=>{const r=new THREE.Mesh(new THREE.CylinderGeometry(.0375,.0375,.018,28),rub);r.rotation.x=Math.PI\/2;r.position.z=z;head.add(r);});\n const hm=mat('#17181b',.55,.2);hm.side=THREE.DoubleSide;const hood=new THREE.Mesh(new THREE.CylinderGeometry(.048,.038,.045,28,1,true),hm);hood.rotation.x=Math.PI\/2;hood.position.z=.162;head.add(hood);\n const glass=new THREE.Mesh(new THREE.CircleGeometry(.03,24),mat('#1d2a40',.05,.3));glass.position.z=.141;head.add(glass);const plate=new THREE.Mesh(new THREE.BoxGeometry(.05,.012,.07),blk);plate.position.y=-.05;head.add(plate);\n g.add(head);const U=g.userData;U.head=head;U.ball=new THREE.Mesh(new THREE.SphereGeometry(.028,16,12),blk);g.add(U.ball);U.col=rod([0,0,0],[0,1,0],.012,al,10);g.add(U.col);U.hub=new THREE.Mesh(new THREE.CylinderGeometry(.045,.04,.05,16),blk);g.add(U.hub);\n U.legs=[];for(let i=0;i<3;i++){const up=rod([0,0,0],[0,1,0],.013,al,8),lo=rod([0,0,0],[0,1,0],.009,al,8),clip=new THREE.Mesh(new THREE.BoxGeometry(.03,.03,.03),blk),ft=new THREE.Mesh(new THREE.SphereGeometry(.014,8,6),rub);g.add(up,lo,clip,ft);U.legs.push({up,lo,clip,ft});}\n U.pick={t:'cam'};S3.scene.add(g);S3.camMark=g;}\nfunction updateTripod(g,h){const U=g.userData;const hubY=Math.max(.3,h-.2);U.head.position.y=h;U.ball.position.y=h-.075;setRod(U.col,[0,hubY,0],[0,h-.07,0]);U.hub.position.y=hubY;const R=clamp(hubY*.45,.22,.6);\n U.legs.forEach((L,i)=>{const a=i*Math.PI*2\/3+Math.PI;const top=[Math.sin(a)*.035,hubY,Math.cos(a)*.035];const foot=[Math.sin(a)*R,.012,Math.cos(a)*R];const mid=[top[0]+(foot[0]-top[0])*.52,top[1]+(foot[1]-top[1])*.52,top[2]+(foot[2]-top[2])*.52];setRod(L.up,top,mid);setRod(L.lo,mid,foot);L.clip.position.set(mid[0],mid[1],mid[2]);L.ft.position.set(foot[0],foot[1],foot[2]);});}\nfunction frustumBox(w,h,depth,bw,bh,m){const geo=new THREE.BoxGeometry(w,h,depth);const p=geo.attributes.position;for(let i=0;i<p.count;i++){if(p.getZ(i)<0){p.setX(i,Math.sign(p.getX(i))*bw\/2);p.setY(i,Math.sign(p.getY(i))*bh\/2);}}p.needsUpdate=true;geo.computeVertexNormals();const o=new THREE.Mesh(geo,m);o.position.z=-depth\/2;return o;}\nfunction lightHead(metal,dark){const h=new THREE.Group();const body=new THREE.Mesh(new THREE.CylinderGeometry(.075,.08,.2,24),metal);body.rotation.x=Math.PI\/2;h.add(body);\n for(let i=0;i<5;i++){const fin=new THREE.Mesh(new THREE.TorusGeometry(.081,.004,6,24),dark);fin.position.z=-.07+i*.03;h.add(fin);}\n const back=new THREE.Mesh(new THREE.CylinderGeometry(.082,.082,.03,24),dark);back.rotation.x=Math.PI\/2;back.position.z=-.11;h.add(back);const ring=new THREE.Mesh(new THREE.TorusGeometry(.078,.009,8,24),dark);ring.position.z=.1;h.add(ring);\n [-1,1].forEach(s=>{const pl=new THREE.Mesh(new THREE.BoxGeometry(.012,.15,.045),dark);pl.position.set(s*.098,-.06,0);h.add(pl);const kn=new THREE.Mesh(new THREE.CylinderGeometry(.018,.018,.02,12),dark);kn.rotation.z=Math.PI\/2;kn.position.set(s*.112,0,0);h.add(kn);});\n const bar=new THREE.Mesh(new THREE.BoxGeometry(.21,.014,.045),dark);bar.position.y=-.135;h.add(bar);const hd=new THREE.Mesh(new THREE.TorusGeometry(.05,.008,6,16,Math.PI),dark);hd.position.set(0,.078,-.03);h.add(hd);return h;}\nfunction buildFixture(L){const md=modOf(L);const m=md.m;const g=new THREE.Group();const fab=mat('#141518',.92,0);fab.side=THREE.DoubleSide;const metal=mat('#34373c',.4,.45),dark=mat('#0f1012',.6,.3),silver=mat('#c4c8ce',.3,.55);silver.side=THREE.DoubleSide;\n const emi=new THREE.MeshStandardMaterial({color:0x000000,emissive:0xffffff,emissiveIntensity:1,roughness:1,side:THREE.DoubleSide});const dep=modDepth(L);let head=true;\n if(m.shape==='rect'){g.add(frustumBox(md.w,md.h,dep,.17,.17,fab));const pn=new THREE.Mesh(new THREE.PlaneGeometry(md.w*.95,md.h*.95),emi);pn.position.z=.006;g.add(pn);const rim=new THREE.Mesh(new THREE.BoxGeometry(md.w+.02,md.h+.02,.025),fab);rim.position.z=-.01;g.add(rim);}\n else if(m.shape==='oct'){const seg=L.mod==='para'?16:8;const sh=new THREE.Mesh(new THREE.CylinderGeometry(md.w\/2,.09,dep,seg,1,true),fab);sh.rotation.x=Math.PI\/2;sh.position.z=-dep\/2;g.add(sh);\n  if(L.mod==='para'){for(let i=0;i<16;i++){const a=i\/16*Math.PI*2;g.add(rod([Math.cos(a)*.09,Math.sin(a)*.09,-dep],[Math.cos(a)*md.w\/2,Math.sin(a)*md.w\/2,0],.005,silver,4));}}\n  const pn=new THREE.Mesh(new THREE.CircleGeometry(md.w\/2*.97,seg),emi);pn.position.z=.006;g.add(pn);}\n else if(L.mod==='dish'){const pts=[];for(let i=0;i<=12;i++){const t=i\/12;pts.push(new THREE.Vector2(.08+t*(md.w\/2-.08),-dep+dep*Math.pow(t,1.6)));}const dish=new THREE.Mesh(new THREE.LatheGeometry(pts,40),silver);dish.rotation.x=Math.PI\/2;g.add(dish);\n  const inner=new THREE.Mesh(new THREE.CircleGeometry(md.w\/2*.93,40),emi);inner.position.z=-dep*.35;g.add(inner);const defl=new THREE.Mesh(new THREE.CylinderGeometry(.075,.075,.01,32),silver);defl.rotation.x=Math.PI\/2;defl.position.z=-.03;g.add(defl);g.add(rod([.075,0,-.03],[.09,0,-dep*.8],.004,silver,4));g.add(rod([-.075,0,-.03],[-.09,0,-dep*.8],.004,silver,4));}\n else if(L.mod==='umb'){const th=.75,R=(md.w\/2)\/Math.sin(th);const dome=new THREE.Mesh(new THREE.SphereGeometry(R,40,14,0,Math.PI*2,0,th),emi);dome.rotation.x=Math.PI\/2;dome.position.z=-R;g.add(dome);\n  for(let i=0;i<8;i++){const a=i\/8*Math.PI*2;g.add(rod([0,0,-.005],[Math.cos(a)*md.w\/2,Math.sin(a)*md.w\/2,-R+R*Math.cos(th)-.005],.004,dark,4));}g.add(rod([0,0,.04],[0,0,-dep-.5],.006,metal,6));}\n else if(L.mod==='fresnel'){head=false;const b=new THREE.Mesh(new THREE.BoxGeometry(.22,.22,.3),metal);b.position.z=-.15;g.add(b);const lens=new THREE.Mesh(new THREE.CircleGeometry(.085,32),emi);lens.position.z=.004;g.add(lens);\n  [[0,.11,0],[0,-.11,Math.PI],[.11,0,-Math.PI\/2],[-.11,0,Math.PI\/2]].forEach(d=>{const door=new THREE.Mesh(new THREE.BoxGeometry(.2,.12,.006),dark);const piv=new THREE.Group();piv.position.set(d[0],d[1],0);piv.rotation.z=d[2];door.position.set(0,.06*Math.cos(.55),.06*Math.sin(.55));door.rotation.x=-(Math.PI\/2-.55);piv.add(door);g.add(piv);});\n  const yk=lightHead(metal,dark);yk.children.slice(0,8).forEach(c=>c.visible=false);yk.position.z=-.18;g.add(yk);}\n else{const cone=new THREE.Mesh(new THREE.CylinderGeometry(md.w\/2,.07,.2,32,1,true),silver);cone.rotation.x=Math.PI\/2;cone.position.z=-.1;g.add(cone);const bulb=new THREE.Mesh(new THREE.CircleGeometry(md.w*.3,24),emi);bulb.position.z=-.06;g.add(bulb);}\n if(L.grid&&m.area){const gp=[];const gw=md.w*.95,gh=(m.shape==='rect'?md.h:md.w)*.95;const n=Math.max(6,Math.round(gw\/.05));for(let i=0;i<=n;i++){const x=-gw\/2+gw*i\/n;gp.push(x,-gh\/2,.012,x,gh\/2,.012);}const nh=Math.max(6,Math.round(gh\/.05));for(let i=0;i<=nh;i++){const y=-gh\/2+gh*i\/nh;gp.push(-gw\/2,y,.012,gw\/2,y,.012);}const lg=new THREE.BufferGeometry();lg.setAttribute('position',new THREE.Float32BufferAttribute(gp,3));g.add(new THREE.LineSegments(lg,new THREE.LineBasicMaterial({color:0x050505})));}\n if(head){const hd=lightHead(metal,dark);hd.position.z=-(dep+.13);g.add(hd);}\n return {g,emi};}\nfunction xMark(col){const g=new THREE.Group();const m=new THREE.MeshBasicMaterial({color:col});[1,-1].forEach(s=>{const b=new THREE.Mesh(new THREE.BoxGeometry(.34,.004,.045),m);b.rotation.y=s*Math.PI\/4;b.position.y=.007;g.add(b);});return g;}\nfunction dashLine(col){const gm=new THREE.BufferGeometry();gm.setAttribute('position',new THREE.Float32BufferAttribute([0,0,0,0,1,0],3));const m=new THREE.LineDashedMaterial({color:col,dashSize:.1,gapSize:.07,transparent:true,opacity:.95,depthTest:false});const l=new THREE.Line(gm,m);l.renderOrder=999;l.frustumCulled=false;return l;}\nfunction setLine(l,a,b){const p=l.geometry.attributes.position;p.setXYZ(0,a.x,a.y,a.z);p.setXYZ(1,b.x,b.y,b.z);p.needsUpdate=true;l.geometry.computeBoundingSphere();l.computeLineDistances();}\nfunction buildStand(boom){const g=new THREE.Group();const al=mat('#8d939b',.4,.45),blk=mat('#17181b',.55,.2),rub=mat('#0c0c0d',.9,0);const U=g.userData;const hubY=.42,R=.46;\n for(let i=0;i<3;i++){const a=i*Math.PI*2\/3+Math.PI\/6;const foot=[Math.sin(a)*R,.012,Math.cos(a)*R];const top=[Math.sin(a)*.03,hubY,Math.cos(a)*.03];g.add(rod(top,foot,.011,al,8));const fb=new THREE.Mesh(new THREE.SphereGeometry(.018,8,6),rub);fb.position.set(foot[0],.014,foot[2]);g.add(fb);\n  const mid=[(top[0]+foot[0])\/2,(top[1]+foot[1])\/2,(top[2]+foot[2])\/2];g.add(rod([Math.sin(a)*.026,.25,Math.cos(a)*.026],mid,.006,al,6));}\n const hub=new THREE.Mesh(new THREE.CylinderGeometry(.032,.032,.1,12),blk);hub.position.y=hubY;g.add(hub);const col=new THREE.Mesh(new THREE.CylinderGeometry(.03,.03,.05,12),blk);col.position.y=.25;g.add(col);\n U.lower=rod([0,.2,0],[0,1,0],.019,al,12);g.add(U.lower);U.upper=rod([0,1,0],[0,2,0],.014,al,12);g.add(U.upper);\n U.knob=new THREE.Group();U.knob.add(new THREE.Mesh(new THREE.CylinderGeometry(.026,.026,.05,12),blk));const kt=rod([0,0,0],[.07,0,0],.007,blk,6);U.knob.add(kt);const kh=new THREE.Mesh(new THREE.CylinderGeometry(.018,.018,.022,10),blk);kh.rotation.z=Math.PI\/2;kh.position.x=.08;U.knob.add(kh);g.add(U.knob);\n U.spig=new THREE.Mesh(new THREE.CylinderGeometry(.009,.009,.1,8),al);g.add(U.spig);\n if(boom){U.arm=rod([0,0,0],[1,0,0],.016,al,10);g.add(U.arm);U.cw=new THREE.Mesh(new THREE.CylinderGeometry(.07,.07,.2,16),blk);g.add(U.cw);U.drop=rod([0,0,0],[0,1,0],.01,al,8);g.add(U.drop);U.clamp=new THREE.Mesh(new THREE.BoxGeometry(.07,.07,.07),blk);g.add(U.clamp);}\n const x=xMark(0xffc53d);g.add(x);U.x=x;return g;}\nfunction createLightObj(L,i){const md=modOf(L);const fx=buildFixture(L);fx.g.userData.pick={t:'light',id:L.id};S3.scene.add(fx.g);const stand=buildStand(L.boom);stand.userData.pick={t:'light',id:L.id};S3.scene.add(stand);\n const spot=new THREE.SpotLight(0xffffff,1,0,Math.PI\/4,.5,2);spot.castShadow=true;spot.shadow.mapSize.set(1024,1024);spot.shadow.camera.near=.1;spot.shadow.camera.far=40;spot.shadow.bias=-0.0005;spot.shadow.normalBias=0.02;S3.scene.add(spot);S3.scene.add(spot.target);\n let rect=null;if(md.m.area&&THREE.RectAreaLight){rect=new THREE.RectAreaLight(0xffffff,1,1,1);S3.scene.add(rect);}\n const col=new THREE.Color(LCOLS[i%5]);const ring=new THREE.Mesh(new THREE.RingGeometry(.3,.37,48),new THREE.MeshBasicMaterial({color:col,transparent:true,opacity:.95,depthTest:false}));ring.rotation.x=-Math.PI\/2;ring.renderOrder=998;S3.scene.add(ring);\n const dl=dashLine(col),hl=dashLine(0x9aa3b5);S3.scene.add(dl);S3.scene.add(hl);return {fx,stand,spot,rect,ring,dl,hl};}\nfunction removeLightObj(o){[o.fx.g,o.stand,o.spot,o.spot.target,o.ring,o.dl,o.hl].forEach(x=>{S3.scene.remove(x);});if(o.rect)S3.scene.remove(o.rect);[o.fx.g,o.stand,o.ring,o.dl,o.hl].forEach(disposeObj);if(o.spot.shadow&&o.spot.shadow.map)o.spot.shadow.map.dispose();}\nfunction syncLight(L,g,i){const sig=L.mod+'|'+L.size+'|'+L.grid+'|'+L.boom+'|'+i;let o=S3.lights[L.id];if(!o||o.sig!==sig){if(o)removeLightObj(o);o=createLightObj(L,i);o.sig=sig;S3.lights[L.id]=o;}o.L=L;\n const lp=lightPos(L,g),tp=aimPt(L,g);const ph=photo(L);const col=lightCol(L);const dir=vnrm(vsub(tp,lp));const pov=MODE==='pov';\n o.fx.g.position.set(lp.x,lp.y,lp.z);o.fx.g.lookAt(tp.x,tp.y,tp.z);o.fx.emi.emissive.setRGB(col[0],col[1],col[2]);\n const mp=mountPos(L,g);const b=standBase(L,g);o.stand.position.set(b.x,0,b.z);const U=o.stand.userData;const lx=mp.x-b.x,lz=mp.z-b.z;\n const top=L.boom?mp.y+.12:Math.max(.55,mp.y-.14);const split=Math.max(.35,Math.min(top-.08,.2+(top-.2)*.55));setRod(U.lower,[0,.2,0],[0,split,0]);setRod(U.upper,[0,split-.06,0],[0,top,0]);U.knob.position.y=split;\n if(L.boom){const len=Math.hypot(lx,lz)||.01;const ux=lx\/len,uz=lz\/len,back=.5;setRod(U.arm,[-ux*back,top,-uz*back],[lx,top,lz]);U.cw.position.set(-ux*back,top-.08,-uz*back);U.clamp.position.set(0,top,0);setRod(U.drop,[lx,top,lz],[lx,mp.y+.06,lz]);U.spig.visible=false;}\n else{U.spig.visible=true;U.spig.position.set(0,top+.05,0);}\n U.x.visible=!!ST.view.marks&&!pov;\n o.spot.position.set(lp.x+dir.x*.06,lp.y+dir.y*.06,lp.z+dir.z*.06);o.spot.target.position.set(tp.x,tp.y,tp.z);o.spot.target.updateMatrixWorld();\n o.spot.angle=Math.min(ph.half,Math.PI\/2-0.02);o.spot.penumbra=ph.pen;o.spot.intensity=L.on?ph.Is:0;o.spot.color.setRGB(col[0],col[1],col[2]);\n const soft=Math.max(ph.md.w,ph.md.h)\/Math.max(0.3,vlen(vsub(lp,tp)));o.spot.shadow.radius=Math.min(24,1+soft*16);\n if(o.rect){o.rect.width=ph.md.m.shape==='rect'?ph.md.w:ph.md.w*.886;o.rect.height=ph.md.m.shape==='rect'?ph.md.h:ph.md.w*.886;o.rect.intensity=L.on?ph.La:0;o.rect.color.setRGB(col[0],col[1],col[2]);o.rect.position.set(lp.x+dir.x*.03,lp.y+dir.y*.03,lp.z+dir.z*.03);o.rect.lookAt(tp.x,tp.y,tp.z);}\n o.ring.position.set(b.x,0.012,b.z);o.ring.visible=L.id===SELL&&!pov;\n const showD=(!!ST.view.dims||L.id===SELL)&&!pov;o.dl.visible=showD;o.hl.visible=showD;if(showD){setLine(o.dl,lp,tp);setLine(o.hl,V(lp.x,0.01,lp.z),lp);}}\nfunction syncScene(){if(!S3)return;const g=geo();const pov=MODE==='pov';const sr=[ST.room.w,ST.room.l,ST.room.h,ST.room.wall].join('|');if(S3.sr!==sr){buildRoom();S3.sr=sr;S3.sb=null;}\n const sb=[ST.bd.on,ST.bd.color,ST.bd.gap,ST.bd.x,ST.bd.w,ST.bd.tex,ST.bd.floor,ST.room.w,ST.room.l,ST.room.h].join('|');if(S3.sb!==sb){buildBackdrop();S3.sb=sb;}\n const ss=ST.subj.type+'|'+(ST.subj.type==='group'?ST.subj.count:1)+'|'+(ST.subj.char||'');if(S3.ss!==ss){buildSubject();S3.ss=ss;}S3.subj.position.set(g.sx,0,g.sz);S3.subj.rotation.y=rad(ST.subj.rot||0);\n const cm=S3.camMark;cm.position.set(g.cam.x,0,g.cam.z);updateTripod(cm,g.cam.y);const AIM=camAim(g);cm.userData.head.lookAt(AIM.x,AIM.y,AIM.z);if(frameAR()<1)cm.userData.head.rotateZ(Math.PI\/2);cm.visible=!pov;\n if(S3.rotRing){const rr=S3.rotRing;rr.position.set(g.sx,.016,g.sz);rr.visible=MODE!=='pov'&&ST.subj.type!=='group';const a=rad(ST.subj.rot||0);rr.userData.knob.position.set(Math.sin(a)*.58,.03,Math.cos(a)*.58);rr.userData.tip.position.set(Math.sin(a)*.74,.03,Math.cos(a)*.74);rr.userData.tip.rotation.set(Math.PI\/2,0,-a);}S3.subjX.position.set(g.sx,0,g.sz);S3.subjX.visible=!!ST.view.marks&&!pov;S3.camX.position.set(g.cam.x,0,g.cam.z);S3.camX.visible=!!ST.view.marks&&!pov;\n const sd=!!ST.view.dims&&!pov;S3.dimBd.visible=sd&&ST.bd.on;S3.dimCam.visible=sd;if(sd){setLine(S3.dimBd,V(g.sx,0.02,g.sz),V(g.sx,0.02,g.bz));setLine(S3.dimCam,V(g.sx,0.02,g.sz),V(g.cam.x,0.02,g.cam.z));}\n const ids=new Set(ST.lights.map(L=>L.id));Object.keys(S3.lights).forEach(id=>{if(!ids.has(id)){removeLightObj(S3.lights[id]);delete S3.lights[id];}});ST.lights.forEach((L,i)=>syncLight(L,g,i));\n const wc=new THREE.Color(WALLS[ST.room.wall].c).convertSRGBToLinear().lerp(new THREE.Color(1,1,1),.4);S3.hemi.color.copy(wc);S3.hemi.groundColor.set(0x3a3b3e);S3.hemi.intensity=ST.room.ambient+bounceLux();\n const c=ST.cam;const ev100=Math.log2(c.N*c.N\/c.t)-Math.log2(c.ISO\/100);S3.renderer.toneMappingExposure=1\/(1.2*Math.pow(2,ev100));\n S3.pov.position.set(g.cam.x,g.cam.y,g.cam.z);S3.pov.lookAt(AIM.x,AIM.y,AIM.z);layoutPOV();\n S3.pickables=[S3.rotRing,S3.subj,S3.camMark,S3.bd].filter(o=>o&&o.visible!==false);Object.values(S3.lights).forEach(o=>{S3.pickables.push(o.fx.g,o.stand);});}\nfunction loop(){requestAnimationFrame(loop);if(!S3||TAB!=='studio')return;if(DIRTY){syncScene();DIRTY=false;}if(S3.clock){const dt=Math.min(.05,S3.clock.getDelta());MIXERS.forEach(m=>m.update(dt));}const ex=S3.renderer.toneMappingExposure;Object.values(S3.lights).forEach(o=>{o.fx.emi.emissiveIntensity=(o.L&&o.L.on)?3\/Math.max(1e-9,ex):0;});\n let camUse=S3.cam;if(MODE==='pov')camUse=S3.pov;else if(MODE==='top'){const r=ST.room;S3.cam.position.set(0,Math.max(r.w,r.l)*1.25+r.h,0.001);S3.cam.lookAt(0,0,0);}else if(S3.controls)S3.controls.update();S3.renderer.render(S3.scene,camUse);drawLabels(camUse);renderPip();}\nfunction setMode(m){const prev=MODE;MODE=m;document.querySelectorAll('.vbar button[data-m]').forEach(b=>b.classList.toggle('on',b.dataset.m===m));if(!S3)return;if(S3.controls)S3.controls.enabled=m==='orbit';\n if(m==='orbit'&&prev==='top')resetView();DIRTY=true;layoutPOV();updPip();}\ndocument.querySelectorAll('.vbar button[data-m]').forEach(b=>b.onclick=()=>setMode(b.dataset.m));\n$('btnOrient').onclick=()=>{flipAspect();};\n$('btnShot').onclick=()=>{if(!S3){toast('Ch\u01b0a kh\u1edfi t\u1ea1o 3D');return;}DIRTY=true;syncScene();S3.renderer.render(S3.scene,MODE==='pov'?S3.pov:S3.cam);const src=S3.renderer.domElement;let url;\n if(MODE==='pov'){const r=frameRect();const k=src.width\/r.W;const c=document.createElement('canvas');c.width=Math.round(r.w*k);c.height=Math.round(r.h*k);const x=ctx2d(c);if(x){x.drawImage(src,r.x*k,r.y*k,r.w*k,r.h*k,0,0,c.width,c.height);url=c.toDataURL('image\/png');}}\n if(!url)url=src.toDataURL('image\/png');const a=document.createElement('a');a.download='kblack-xem-truoc-'+Date.now()+'.png';a.href=url;a.click();toast('\u0110\u00e3 l\u01b0u \u1ea3nh xem tr\u01b0\u1edbc');};\n$('btnDiag').onclick=()=>{const c=document.createElement('canvas');c.width=1400;c.height=2050;const x=ctx2d(c);if(!x)return;const pc=document.createElement('canvas');pc.width=1400;pc.height=1400;drawPlan(pc,true);x.fillStyle='#0b101d';x.fillRect(0,0,1400,2050);x.drawImage(pc,0,0);\n const M=meter();const g=geo();const c0=ST.cam;x.fillStyle='#fff';x.font='700 38px \"Be Vietnam Pro\"';x.fillText('S\u01a1 \u0111\u1ed3 \u00e1nh s\u00e1ng \u2014 K-BLACK',60,1470);x.font='500 23px \"Be Vietnam Pro\"';x.fillStyle='#8e9ab3';\n x.fillText('Ph\u00f2ng '+ST.room.w+' \u00d7 '+ST.room.l+' m, tr\u1ea7n '+ST.room.h+' m.  M\u00e1y '+c0.focal+'mm, f\/'+c0.N+', '+fmtT(c0.t)+', ISO '+c0.ISO+'.  \u0110o s\u00e1ng \u0111\u1ec1 xu\u1ea5t '+fmtN(M.Nrec)+(M.grp?', nh\u00f3m ch\u00eanh '+M.grp.spread.toFixed(1)+' stop':'')+'.',60,1510);\n x.fillText('D\u1ea5u X ch\u1ee7 th\u1ec3: '+wallCoords(V(g.sx,0,g.sz))+'.   D\u1ea5u X m\u00e1y: '+wallCoords(V(g.cam.x,0,g.cam.z))+'.',60,1546);\n ST.lights.forEach((L,i)=>{const md=modOf(L);const y=1600+i*84;x.fillStyle=LCOLS[i%5];x.fillRect(60,y-17,18,18);x.fillStyle='#e9eef7';x.font='700 24px \"Be Vietnam Pro\"';x.fillText(L.name+' ('+roleShort(L.role)+')'+(L.on?'':' \u2014 \u0111ang t\u1eaft'),92,y);x.font='500 21px \"Be Vietnam Pro\"';x.fillStyle='#b9c3d8';\n  x.fillText(md.m.n+' '+md.label+(L.grid?' + t\u1ed5 ong':'')+', '+(L.kind==='flash'?'flash ':'LED ')+L.power+(L.kind==='flash'?'Ws':'W')+', '+azFmt(L.az)+', c\u00e1ch ch\u1ee7 th\u1ec3 '+L.dist+' m, cao '+L.height+' m'+(L.boom?', ch\u00e2n boom':''),92,y+30);x.fillStyle='#8e9ab3';x.fillText('D\u1ea5u X ch\u00e2n \u0111\u00e8n: '+wallCoords(standBase(L,g)),92,y+58);});\n const a=document.createElement('a');a.download='kblack-so-do-den.png';a.href=c.toDataURL('image\/png');a.click();toast('\u0110\u00e3 t\u1ea3i s\u01a1 \u0111\u1ed3 \u0111\u00e8n');};\n\/* ----- saved setups ----- *\/\nfunction readSets(){try{return JSON.parse(localStorage.getItem('kblack_lab_sets')||'[]');}catch(e){return [];}}\n$('btnSaveSet').onclick=()=>{const n=prompt('T\u00ean setup:','Setup '+(readSets().length+1));if(n===null)return;const a=readSets();a.unshift({name:n||'Setup',st:JSON.parse(JSON.stringify(ST))});try{localStorage.setItem('kblack_lab_sets',JSON.stringify(a));toast('\u0110\u00e3 l\u01b0u \"'+(n||'Setup')+'\"');}catch(e){toast('Kh\u00f4ng l\u01b0u \u0111\u01b0\u1ee3c \u2014 b\u1ed9 nh\u1edb tr\u00ecnh duy\u1ec7t \u0111\u1ea7y');}};\n$('btnMySet').onclick=()=>{const L=$('setList');L.innerHTML='';const a=readSets();if(!a.length)L.innerHTML='<p class=\"note\" style=\"margin-top:12px\">Ch\u01b0a c\u00f3 setup n\u00e0o. D\u1ef1ng xong b\u1ea5m \"L\u01b0u setup\" \u0111\u1ec3 gi\u1eef l\u1ea1i.<\/p>';\n a.forEach((s,i)=>{const r=el('div','srow','<span>'+s.name+'<\/span>');const o=el('button','tbtn','M\u1edf');o.onclick=()=>{ST=JSON.parse(JSON.stringify(s.st));SELL=ST.lights[0]?ST.lights[0].id:null;$('setModal').classList.remove('show');buildLeft();buildRight();changed();syncOrientBtn();toast('\u0110\u00e3 m\u1edf '+s.name);};const d=el('button','tbtn','Xo\u00e1');d.onclick=()=>{const b=readSets();b.splice(i,1);try{localStorage.setItem('kblack_lab_sets',JSON.stringify(b));}catch(e){}r.remove();};r.append(o,d);L.appendChild(r);});$('setModal').classList.add('show');};\n$('setClose').onclick=()=>$('setModal').classList.remove('show');\n$('setModal').onclick=e=>{if(e.target===$('setModal'))$('setModal').classList.remove('show');};\n\n\/* ----- view helpers, labels, HUD, direct 3D manipulation, shortcuts ----- *\/\nfunction resetView(){if(!S3)return;const r=ST.room;S3.cam.position.set(r.w*0.95,Math.min(r.h*1.3,6.5),r.l*0.9);if(S3.controls){S3.controls.target.set(0,1.1,-r.l*0.08);S3.controls.update();}else S3.cam.lookAt(0,1.1,0);}\nfunction toggleView(k){ST.view[k]=!ST.view[k];syncViewBtns();DIRTY=true;drawPlan($('plan'));saveSoon();}\nfunction syncViewBtns(){document.querySelectorAll('.vbar [data-v]').forEach(b=>{const on=!!(ST.view&&ST.view[b.dataset.v]);b.classList.toggle('on',on);b.setAttribute('aria-pressed',on);});}\nfunction updHUD(){const h=$('hud');if(!h)return;const L=ST.lights.find(x=>x.id===SELL);const g=geo();if(!L){h.innerHTML='<div class=\"hint\">B\u1ea5m v\u00e0o m\u1ed9t \u0111\u00e8n trong khung 3D ho\u1eb7c tr\u00ean m\u1eb7t b\u1eb1ng \u0111\u1ec3 ch\u1ecdn.<\/div>';return;}const md=modOf(L);const lp=lightPos(L,g),tp=aimPt(L,g);\n h.innerHTML='<div><b>'+L.name+'<\/b><span class=\"sep\"><\/span>'+md.m.n+' '+md.label+(L.grid?' + t\u1ed5 ong':'')+'<span class=\"sep\"><\/span>'+(L.kind==='flash'?'Flash ':'LED ')+L.power+(L.kind==='flash'?'Ws':'W')+(L.boom?'<span class=\"sep\"><\/span>ch\u00e2n boom':'')+'<span class=\"sep\"><\/span>t\u1edbi \u0111i\u1ec3m chi\u1ebfu <span class=\"n\">'+vlen(vsub(lp,tp)).toFixed(2)+' m<\/span><span class=\"sep\"><\/span>cao <span class=\"n\">'+L.height.toFixed(2)+' m<\/span><span class=\"sep\"><\/span>'+azFmt(L.az)+'<\/div><div class=\"hint\">D\u1ea5u X: '+wallCoords(standBase(L,g))+'. K\u00e9o \u0111\u00e8n \u0111\u1ec3 di chuy\u1ec3n, gi\u1eef Shift khi k\u00e9o \u0111\u1ec3 n\u00e2ng h\u1ea1. Ph\u00edm \u2190 \u2192 \u0111\u1ed5i g\u00f3c, \u2191 \u2193 kho\u1ea3ng c\u00e1ch, [ ] \u0111\u1ed9 cao.<\/div>';}\nfunction projectPt(p,cam,W,H){const v=new THREE.Vector3(p.x,p.y,p.z).project(cam);return {x:(v.x+1)\/2*W,y:(1-v.y)\/2*H,ok:v.z<1&&v.z>-1};}\nfunction drawLabels(cam){const lay=$('labels');if(!lay)return;const items=[];const pov=MODE==='pov';\n if(!pov){const g=geo();ST.lights.forEach((L,i)=>{const lp=lightPos(L,g),tp=aimPt(L,g);if(ST.view.tags)items.push({p:V(lp.x,lp.y+0.45,lp.z),t:'<i style=\"background:'+LCOLS[i%5]+'\"><\/i>'+L.name,c:'tag'+(L.id===SELL?' sel':'')+(L.on?'':' off')});\n  if(ST.view.dims||L.id===SELL){items.push({p:V((lp.x+tp.x)\/2,(lp.y+tp.y)\/2,(lp.z+tp.z)\/2),t:vlen(vsub(lp,tp)).toFixed(2)+' m',c:'dim'});items.push({p:V(lp.x,lp.y\/2,lp.z),t:'cao '+lp.y.toFixed(2),c:'dim h'});}});\n  if(ST.subj.type!=='group'){const a=rad(ST.subj.rot||0);items.push({p:V(g.sx+Math.sin(a)*.9,.05,g.sz+Math.cos(a)*.9),t:'\u21bb '+(ST.subj.rot||0)+'\u00b0',c:'dim rot'});}\n  if(ST.view.dims){if(ST.bd.on)items.push({p:V(g.sx,0.03,(g.sz+g.bz)\/2),t:'t\u1edbi ph\u00f4ng '+(g.sz-g.bz).toFixed(2)+' m',c:'dim'});items.push({p:V((g.sx+g.cam.x)\/2,0.03,(g.sz+g.cam.z)\/2),t:'m\u00e1y '+camDist(g).toFixed(2)+' m',c:'dim'});}}\n const W=lay.clientWidth||800,H=lay.clientHeight||600;while(lay.children.length<items.length)lay.appendChild(el('div','lb'));\n for(let i=0;i<lay.children.length;i++){const d=lay.children[i];const it=items[i];if(!it){d.style.display='none';continue;}const s=projectPt(it.p,cam,W,H);if(!s.ok){d.style.display='none';continue;}d.style.display='';const cls='lb '+it.c;if(d.className!==cls)d.className=cls;if(d._t!==it.t){d.innerHTML=it.t;d._t=it.t;}d.style.transform='translate('+Math.round(s.x)+'px,'+Math.round(s.y)+'px) translate(-50%,-50%)';}}\nfunction initPicking(){const host=$('view3d');const ray=new THREE.Raycaster();const ndc=new THREE.Vector2();const tmp=new THREE.Vector3();const tip=$('dragTip');let D=null;\n function setNdc(e){const r=S3.renderer.domElement.getBoundingClientRect();ndc.set(((e.clientX-r.left)\/Math.max(1,r.width))*2-1,-((e.clientY-r.top)\/Math.max(1,r.height))*2+1);ray.setFromCamera(ndc,S3.cam);}\n function pick(e){setNdc(e);const hits=ray.intersectObjects(S3.pickables||[],true);for(const h of hits){let o=h.object;while(o&&!(o.userData&&o.userData.pick))o=o.parent;if(o&&o.userData.pick)return {info:o.userData.pick,point:h.point};}return null;}\n function hitPlane(e,plane){setNdc(e);return ray.ray.intersectPlane(plane,tmp)?tmp.clone():null;}\n function showTip(e){if(!D)return;const g=geo();let h='';if(D.t==='light'){const L=D.L;const lp=lightPos(L,g),tp=aimPt(L,g);h='<b>'+L.name+'<\/b><div><span class=\"n\">'+vlen(vsub(lp,tp)).toFixed(2)+' m<\/span> t\u1edbi \u0111i\u1ec3m chi\u1ebfu, cao <span class=\"n\">'+L.height.toFixed(2)+' m<\/span><\/div><div>'+azFmt(L.az)+', c\u00e1ch ch\u1ee7 th\u1ec3 '+L.dist.toFixed(2)+' m<\/div><div class=\"mut\">X: '+wallCoords(standBase(L,g))+'<\/div>';}\n  else if(D.t==='bd')h='<b>Ph\u00f4ng n\u1ec1n<\/b><div>c\u00e1ch t\u01b0\u1eddng sau <span class=\"n\">'+ST.bd.gap.toFixed(2)+' m<\/span>, '+(Math.abs(ST.bd.x)<0.01?'gi\u1eefa ph\u00f2ng':(ST.bd.x>0?'l\u1ec7ch ph\u1ea3i ':'l\u1ec7ch tr\u00e1i ')+Math.abs(ST.bd.x).toFixed(2)+' m')+'<\/div><div>c\u00e1ch ng\u01b0\u1eddi m\u1eabu <span class=\"n\">'+ST.subj.bd.toFixed(2)+' m<\/span><\/div>';\n  else if(D.t==='rot')h='<b>Xoay ng\u01b0\u1eddi<\/b><div><span class=\"n\">'+(ST.subj.rot||0)+'\u00b0<\/span> '+((ST.subj.rot||0)===0?'nh\u00ecn th\u1eb3ng m\u00e1y':(ST.subj.rot>0?'quay sang ph\u1ea3i khung':'quay sang tr\u00e1i khung'))+'<\/div><div class=\"mut\">K\u00e9o n\u00fam cam v\u00f2ng quanh ch\u00e2n<\/div>';\n  else if(D.t==='subj')h='<b>Ch\u1ee7 th\u1ec3<\/b><div>c\u00e1ch ph\u00f4ng <span class=\"n\">'+ST.subj.bd.toFixed(2)+' m<\/span><\/div><div class=\"mut\">X: '+wallCoords(V(g.sx,0,g.sz))+'<\/div>';\n  else h='<b>M\u00e1y \u1ea3nh<\/b><div>c\u00e1ch ch\u1ee7 th\u1ec3 <span class=\"n\">'+camDist(g).toFixed(2)+' m<\/span>, '+azFmt(ST.cam.az||0)+'<\/div><div class=\"mut\">X: '+wallCoords(V(g.cam.x,0,g.cam.z))+'<\/div>';\n  tip.innerHTML=h;tip.style.display='block';tip.style.left=Math.min(window.innerWidth-260,e.clientX+16)+'px';tip.style.top=(e.clientY+16)+'px';}\n function endDrag(){if(!D){if(S3&&S3.controls)S3.controls.enabled=MODE==='orbit';return;}D=null;tip.style.display='none';host.style.cursor='';if(S3.controls)S3.controls.enabled=MODE==='orbit';buildLeft();buildRight();saveSoon();histSave();}\n host.addEventListener('pointerdown',e=>{if(!S3||MODE==='pov'||e.button!==0)return;const h=pick(e);if(!h)return;e.preventDefault();e.stopPropagation();if(S3.controls)S3.controls.enabled=false;const g=geo();const up=new THREE.Vector3(0,1,0);\n  if(h.info.t==='light'){const L=ST.lights.find(x=>x.id===h.info.id);if(!L){endDrag();return;}SELL=L.id;buildRight();DIRTY=true;const lp=lightPos(L,g);const vertical=(e.shiftKey||e.altKey)&&MODE==='orbit';let plane;\n   if(vertical){const n=new THREE.Vector3();S3.cam.getWorldDirection(n);n.y=0;if(n.lengthSq()<1e-6)n.set(0,0,1);n.normalize();plane=new THREE.Plane().setFromNormalAndCoplanarPoint(n,new THREE.Vector3(lp.x,lp.y,lp.z));}else plane=new THREE.Plane(up,-lp.y);\n   const p0=hitPlane(e,plane);if(!p0){D=null;endDrag();return;}D={t:'light',L,plane,vertical,off:V(p0.x-lp.x,p0.y-lp.y,p0.z-lp.z)};}\n  else if(h.info.t==='rot'){D={t:'rot',plane:new THREE.Plane(up,0)};}\n  else if(h.info.t==='bd'){const plane=new THREE.Plane(up,0);const p0=hitPlane(e,plane);if(!p0){endDrag();return;}D={t:'bd',plane,off:V(p0.x-g.bx,0,p0.z-g.bz)};}\n  else if(h.info.t==='subj'){const plane=new THREE.Plane(up,0);const p0=hitPlane(e,plane);if(!p0){endDrag();return;}D={t:'subj',plane,off:V(p0.x-g.sx,0,p0.z-g.sz)};}\n  else{const plane=new THREE.Plane(up,0);const p0=hitPlane(e,plane);if(!p0){endDrag();return;}D={t:'cam',plane,off:V(p0.x-g.cam.x,0,p0.z-g.cam.z)};}\n  host.style.cursor='grabbing';showTip(e);},true);\n window.addEventListener('pointermove',e=>{if(!S3)return;if(!D){if(TAB==='studio'&&MODE!=='pov'&&!e.buttons&&e.target&&e.target.nodeType===1&&host.contains(e.target))host.style.cursor=pick(e)?'grab':'';return;}\n  const p=hitPlane(e,D.plane);if(!p)return;const g=geo();const r=ST.room;\n  if(D.t==='light'){const L=D.L;if(D.vertical){L.height=Math.round(clamp(p.y-D.off.y,0.2,r.h-0.1)*100)\/100;}else{const x=clamp(p.x-D.off.x,-r.w\/2+0.1,r.w\/2-0.1),z=clamp(p.z-D.off.z,-r.l\/2+0.1,r.l\/2-0.1);const dx=x-g.sx,dz=z-g.sz;L.az=Math.round(Math.atan2(dx,dz)*180\/Math.PI);L.dist=Math.round(clamp(Math.hypot(dx,dz),0.3,8)*100)\/100;}}\n  else if(D.t==='bd'){moveBd(Math.round((p.x-D.off.x)*100)\/100,Math.round((p.z-D.off.z+r.l\/2)*100)\/100);}\n  else if(D.t==='rot'){ST.subj.rot=wrapAz(Math.round(Math.atan2(p.x-g.sx,p.z-g.sz)*180\/Math.PI\/5)*5);}\n  else if(D.t==='subj'){ST.subj.x=Math.round(clamp(p.x-D.off.x,-r.w\/2+0.3,r.w\/2-0.3)*100)\/100;ST.subj.bd=Math.round(clamp(p.z-D.off.z-g.bz,0.4,r.l-ST.bd.gap-0.5)*100)\/100;}\n  else{const dx=p.x-D.off.x-g.sx,dz=p.z-D.off.z-g.sz;ST.cam.dist=Math.round(clamp(Math.hypot(dx,dz),0.5,12)*100)\/100;ST.cam.az=Math.round(Math.atan2(dx,dz)*180\/Math.PI);}\n  DIRTY=true;drawPlan($('plan'));updateMeter();showTip(e);});\n window.addEventListener('pointerup',endDrag);window.addEventListener('pointercancel',endDrag);}\nfunction initKeys(){document.addEventListener('keydown',e=>{if(TAB!=='studio')return;const tg=e.target;if(tg&&\/INPUT|SELECT|TEXTAREA\/.test(tg.tagName))return;const k=e.key;const mod=e.ctrlKey||e.metaKey;\n if(mod&&k.toLowerCase()==='z'){e.preventDefault();e.shiftKey?doRedo():doUndo();return;}if(mod&&k.toLowerCase()==='y'){e.preventDefault();doRedo();return;}if(mod)return;\n if(k==='1'){setMode('orbit');return;}if(k==='2'){setMode('pov');return;}if(k==='3'){setMode('top');return;}if(k==='d'||k==='D'){toggleView('dims');return;}if(k==='x'||k==='X'){toggleView('marks');return;}\n const L=ST.lights.find(x=>x.id===SELL);if(!L)return;const st=e.shiftKey?5:1;const hmax=ST.room.h-0.1;let hit=true;\n if(k==='ArrowLeft')L.az=wrapAz(L.az-5*st);else if(k==='ArrowRight')L.az=wrapAz(L.az+5*st);else if(k==='ArrowUp')L.dist=clamp(+(L.dist+0.05*st).toFixed(2),0.3,8);else if(k==='ArrowDown')L.dist=clamp(+(L.dist-0.05*st).toFixed(2),0.3,8);\n else if(k===']'||k==='PageUp')L.height=clamp(+(L.height+0.05*st).toFixed(2),0.2,hmax);else if(k==='['||k==='PageDown')L.height=clamp(+(L.height-0.05*st).toFixed(2),0.2,hmax);\n else if(k==='Delete'){ST.lights=ST.lights.filter(x=>x.id!==L.id);SELL=ST.lights[0]?ST.lights[0].id:null;}\n else if(k==='Tab'){const i=ST.lights.indexOf(L);SELL=ST.lights[(i+(e.shiftKey?-1:1)+ST.lights.length)%ST.lights.length].id;}else hit=false;\n if(hit){e.preventDefault();changed(true);}});}\n\n\/* ---------- real assets: photos & scanned head ---------- *\/\nfunction ph(k){return (window.KB_PHOTOS||{})[k]||'';}\nfunction loadImg(k,cb){const im=new Image();im.onload=()=>cb&&cb(im);im.src=ph(k);return im;}\nfunction imgReady(im){return im&&im.complete&&im.naturalWidth>0;}\nfunction drawCover(ctx,im,W,H,fy){const r=Math.max(W\/im.naturalWidth,H\/im.naturalHeight);const w=im.naturalWidth*r,h=im.naturalHeight*r;ctx.drawImage(im,(W-w)\/2,(H-h)*(fy==null?.5:fy),w,h);}\nfunction fillPhotos(root){root.querySelectorAll('img[data-ph]').forEach(i=>{if(!i.getAttribute('src'))i.src=ph(i.dataset.ph);});}\nfunction b64ToBuf(b){const s=atob(b);const u=new Uint8Array(s.length);for(let i=0;i<s.length;i++)u[i]=s.charCodeAt(i);return u.buffer;}\nfunction parseHeadGLB(buf){const dv=new DataView(buf);const jl=dv.getUint32(12,true);const jb=new Uint8Array(buf,20,jl);let js='';for(let i=0;i<jb.length;i++)js+=String.fromCharCode(jb[i]);const json=JSON.parse(js);const binOff=20+jl+8;const prim=json.meshes[0].primitives[0];\n const acc=i=>{const a=json.accessors[i],bv=json.bufferViews[a.bufferView];const off=binOff+(bv.byteOffset||0)+(a.byteOffset||0);const n={SCALAR:1,VEC2:2,VEC3:3}[a.type];const T=a.componentType===5126?Float32Array:a.componentType===5125?Uint32Array:Uint16Array;return new T(buf.slice(off,off+a.count*n*T.BYTES_PER_ELEMENT));};\n const pos=acc(prim.attributes.POSITION),nor=acc(prim.attributes.NORMAL),uv=acc(prim.attributes.TEXCOORD_0);const idx=acc(prim.indices);\n const cut=-1.25,keep=[];for(let t=0;t<idx.length;t+=3){const a=idx[t],b=idx[t+1],c=idx[t+2];if(pos[a*3+1]<cut&&pos[b*3+1]<cut&&pos[c*3+1]<cut)continue;keep.push(a,b,c);}\n const g=new THREE.BufferGeometry();g.setAttribute('position',new THREE.BufferAttribute(pos,3));g.setAttribute('normal',new THREE.BufferAttribute(nor,3));g.setAttribute('uv',new THREE.BufferAttribute(uv,2));g.setIndex(keep);\n const s=0.048;g.translate(0,-3.97,-0.33);g.scale(s,s,s);g.translate(0,1.785,0);g.computeBoundingSphere();g.computeBoundingBox();return g;}\nfunction initHead(){if(!S3||S3.headGeo||S3.headLd||!window.KB_ASSETS)return;S3.headLd=1;fetch(KB_ASSETS.headUrl).then(r=>r.arrayBuffer()).then(buf=>{try{S3.headGeo=parseHeadGLB(buf);const tl=new THREE.TextureLoader();const map=tl.load(KB_ASSETS.colUrl,()=>{DIRTY=true;});map.encoding=THREE.sRGBEncoding;const nrm=tl.load(KB_ASSETS.nrmUrl);\n S3.headMat=new THREE.MeshStandardMaterial({map,normalMap:nrm,roughness:.55,metalness:0});S3.ss=null;DIRTY=true;if(S3.subj&&typeof buildSubject==='function')buildSubject();}catch(e){S3.headGeo=null;console.warn('head',e);}}).catch(e=>console.warn('head',e));}\n\/* ---------- exposure simulator on a real K-BLACK photo ---------- *\/\nfunction initExpo(){const cv=$('expoCv');const ctx=ctx2d(cv);const S={ai:4,si:2,ii:0,scene:15,nd:0};const NS=SHS.length-1;const NDS=[[0,'Kh\u00f4ng'],[1,'ND2 (\u22121 stop)'],[2,'ND4 (\u22122)'],[3,'ND8 (\u22123)'],[6,'ND64 (\u22126)'],[10,'ND1000 (\u221210)']];\n const SCN=[[15,'N\u1eafng g\u1eaft ngo\u00e0i tr\u1eddi (EV 15)'],[13,'B\u00f3ng r\u00e2m, tr\u1eddi nhi\u1ec1u m\u00e2y (EV 13)'],[10,'Trong nh\u00e0 s\u00e1ng, c\u1ea1nh c\u1eeda s\u1ed5 (EV 10)'],[7,'Trong nh\u00e0 \u0111\u00e8n th\u01b0\u1eddng (EV 7)'],[4,'\u0110\u01b0\u1eddng ph\u1ed1 v\u1ec1 \u0111\u00eam (EV 4)']];\n const userLayer=!!(slotURL('expo_bg')&&slotURL('expo_subject')&&(ASSETS.photos||{}).expo_bg);const EX=window.KB_EXPO;const stackMode=!userLayer&&!!EX;\n let W=960,H=540;if(stackMode){W=EX.w;H=EX.h;cv.width=W;cv.height=H;cv.parentElement.classList.add('side');}\n const C=$('expoCtl');\n C.appendChild(sld('Kh\u1ea9u \u0111\u1ed9',0,APS.length-1,1,S.ai,v=>'f\/'+APS[v],v=>{S.ai=v;draw();},1));\n C.appendChild(sld('T\u1ed1c \u0111\u1ed9',0,NS,1,NS-S.si,v=>fmtT(SHS[NS-v]),v=>{S.si=NS-v;draw();},1));\n C.appendChild(sld('ISO',0,ISS.length-1,1,S.ii,v=>''+ISS[v],v=>{S.ii=v;draw();},1));\n const sc=selc('B\u1ed1i c\u1ea3nh',SCN,S.scene,v=>{S.scene=+v;draw();});const ndc=selc('K\u00ednh l\u1ecdc ND',NDS,S.nd,v=>{S.nd=+v;draw();});if(!stackMode)sc.style.gridColumn='1 \/ 3';C.appendChild(sc);C.appendChild(ndc);\n const auto=el('button','gbtn','T\u1ef1 c\u00e2n s\u00e1ng theo kh\u1ea9u');auto.style.alignSelf='end';auto.style.marginBottom='10px';auto.onclick=()=>{const N=APS[S.ai],ISO=ISS[S.ii];const want=N*N\/Math.pow(2,S.scene-S.nd+Math.log2(ISO\/100));let best=0;SHS.forEach((t,i)=>{if(Math.abs(Math.log2(t\/want))<Math.abs(Math.log2(SHS[best]\/want)))best=i;});S.si=best;const r=C.children[1];r._r.value=NS-best;r._v.textContent=fmtT(SHS[best]);draw();};C.appendChild(auto);\n const mk=()=>{const c=document.createElement('canvas');c.width=W;c.height=H;return c;};const noise=mk(),sharp=mk();const n=ctx2d(noise),sh=ctx2d(sharp);\n if(n&&n.createImageData){const id=n.createImageData(W,H);if(id&&id.data){for(let i=0;i<id.data.length;i+=4){const v=Math.random()*255;id.data[i]=v;id.data[i+1]=v*(0.8+Math.random()*0.4);id.data[i+2]=v;id.data[i+3]=255;}n.putImageData(id,0,0);}}\n const L={bg:null,subj:null,mov:null,photo:null,lv:[],sub:null};\n if(stackMode){EX.levels.forEach((u,i)=>{const im=new Image();im.onload=()=>{if(i===S.ai)draw();};im.src=u;L.lv[i]=im;});const si=new Image();si.onload=()=>draw();si.src=EX.subj;L.sub=si;}\n else if(userLayer){const layer=(slot,key)=>{const u=slotURL(slot);if(!u)return;const im=new Image();im.crossOrigin='anonymous';im.onload=()=>{L[key]=im;draw();};im.src=u;};layer('expo_bg','bg');layer('expo_subject','subj');layer('expo_motion','mov');}\n else simImg('expo_portrait','ap_deep',im=>{L.photo=im;draw();});\n function fitH(im,h){const s=h\/im.naturalHeight;return [im.naturalWidth*s,h];}\n function draw(){if(!$('expoVer')||!document.body.contains(cv))return;const N=APS[S.ai],t=SHS[S.si],ISO=ISS[S.ii];const evSet=Math.log2(N*N\/t)-Math.log2(ISO\/100);const over=S.scene-S.nd-evSet;const br=clamp(Math.pow(2,over\/2.2),0.06,4);\n  const shake=t>1\/30?Math.min(6,(Math.log2(t*30)+1)*1.6):0;const bgBlur=clamp(22*1.4\/N,0.3,22);let movLen=0;const bf='brightness('+br.toFixed(3)+')';\n  if(ctx){ctx.fillStyle='#0b0f1a';ctx.fillRect(0,0,W,H);\n   if(stackMode){const lv=L.lv[S.ai];if(imgReady(lv)&&imgReady(L.sub)){ctx.save();ctx.filter=bf+(shake?' blur('+shake.toFixed(1)+'px)':'');ctx.drawImage(lv,0,0,W,H);ctx.drawImage(L.sub,0,0,W,H);ctx.restore();}else{ctx.fillStyle='#8e9ab3';ctx.font='600 20px \"Be Vietnam Pro\"';ctx.fillText('\u0110ang t\u1ea3i \u1ea3nh\u2026',30,50);}}\n   else if(userLayer&&imgReady(L.bg)&&imgReady(L.subj)){ctx.save();ctx.filter=bf+' blur('+(bgBlur+shake).toFixed(1)+'px)';const r=Math.max(W\/L.bg.naturalWidth,H\/L.bg.naturalHeight)*1.04;ctx.drawImage(L.bg,(W-L.bg.naturalWidth*r)\/2,(H-L.bg.naturalHeight*r)\/2,L.bg.naturalWidth*r,L.bg.naturalHeight*r);ctx.restore();\n    if(imgReady(L.mov)){const d=fitH(L.mov,H*0.42);movLen=Math.min(360,2200*t);const cnt=Math.max(1,Math.min(28,Math.round(movLen\/8)));ctx.save();ctx.filter=bf+' blur('+(bgBlur*0.55+shake).toFixed(1)+'px)';for(let i=0;i<cnt;i++){ctx.globalAlpha=cnt===1?1:Math.min(1,2.4\/cnt);ctx.drawImage(L.mov,W*0.62+i*(movLen\/cnt),H*0.93-d[1],d[0],d[1]);}ctx.restore();}\n    const d=fitH(L.subj,H*0.96);ctx.save();ctx.filter=bf+(shake?' blur('+shake.toFixed(1)+'px)':'');ctx.drawImage(L.subj,(W-d[0])\/2,H-d[1],d[0],d[1]);ctx.restore();}\n   else if(imgReady(L.photo)){ctx.save();ctx.filter=bf+' blur('+(bgBlur+shake).toFixed(1)+'px)';drawCover(ctx,L.photo,W,H,.25);ctx.restore();if(sh){sh.clearRect(0,0,W,H);sh.save();sh.filter=bf+(shake?' blur('+shake.toFixed(1)+'px)':'');drawCover(sh,L.photo,W,H,.25);sh.restore();sh.save();sh.globalCompositeOperation='destination-in';sh.translate(W\/2,H*.55);sh.scale(1,2.1);const g=sh.createRadialGradient(0,0,70,0,0,165);g.addColorStop(0,'rgba(0,0,0,1)');g.addColorStop(1,'rgba(0,0,0,0)');sh.fillStyle=g;sh.fillRect(-600,-400,1200,800);sh.restore();ctx.drawImage(sharp,0,0);}}\n   const nl=Math.max(0,Math.log2(ISO\/100))*0.05;if(nl>0){ctx.save();ctx.globalAlpha=nl;ctx.globalCompositeOperation='overlay';ctx.drawImage(noise,0,0);ctx.restore();}\n   drawHist($('expoHist'),histogramOf(ctx,W,H,3));}\n  $('expoRead').innerHTML='\u0110o c\u1ea3nh <b>EV '+S.scene+'<\/b>'+(S.nd?' &nbsp; ND <b>\u2212'+S.nd+'<\/b>':'')+' &nbsp; M\u00e1y <b>EV '+evSet.toFixed(1)+'<\/b> &nbsp; Ph\u00f4ng <b>'+(N<=2?'tan h\u1eb3n':N<=4?'m\u1edd r\u00f5':N<=8?'m\u1edd nh\u1eb9':'n\u00e9t')+'<\/b>'+(imgReady(L.mov)&&userLayer?' &nbsp; Nho\u00e8 chuy\u1ec3n \u0111\u1ed9ng <b>'+(movLen>14?'r\u00f5':'kh\u00f4ng')+'<\/b>':'')+' &nbsp; Rung tay <b>'+(shake?'c\u00f3':'kh\u00f4ng')+'<\/b>';\n  const v=$('expoVer');const notes=[];if(t>1\/60)notes.push('t\u1ed1c ch\u1eadm d\u1ec5 rung tay');if(ISO>=1600)notes.push('ISO cao, nhi\u1ec5u r\u00f5');if(N<=2.8)notes.push('ph\u00f4ng xo\u00e1 m\u1ea1nh');\n  if(Math.abs(over)<0.34){v.className='verdict ok';v.textContent='\u0110\u00fang s\u00e1ng'+(notes.length?' \u2014 '+notes.join(', '):'');}\n  else if(over>0){v.className='verdict over';const ndNeed=NDS.find(x=>x[0]>=Math.ceil(over-0.3)+S.nd);v.textContent='D\u01b0 s\u00e1ng '+over.toFixed(1)+' stop \u2014 '+(S.si===0&&ISO===ISS[0]?'\u0111\u00e3 h\u1ebft t\u1ed1c t\u1ed1i \u0111a 1\/4000 v\u00e0 ISO th\u1ea5p nh\u1ea5t. C\u1ea7n k\u00ednh l\u1ecdc '+(ndNeed?ndNeed[1].split(' ')[0]:'ND m\u1ea1nh h\u01a1n')+' \u0111\u1ec3 gi\u1eef f\/'+N+', ho\u1eb7c \u0111\u00f3ng kh\u1ea9u':'\u0111\u00f3ng kh\u1ea9u, t\u0103ng t\u1ed1c ho\u1eb7c h\u1ea1 ISO');}\n  else{v.className='verdict under';v.textContent='Thi\u1ebfu s\u00e1ng '+(-over).toFixed(1)+' stop \u2014 m\u1edf kh\u1ea9u, gi\u1ea3m t\u1ed1c ho\u1eb7c t\u0103ng ISO';}}\n draw();}\n\/* ---------- metering lesson on real photos ---------- *\/\nfunction initHist(){const cv=$('histImg');const ctx=ctx2d(cv);const S={bg:'white',ev:0};const P={white:['white','N\u1ec1n tr\u1eafng'],blue:['portrait','N\u1ec1n trung t\u00ednh'],black:['dark_event','C\u1ea3nh t\u1ed1i']};const imgs={},avg={};\n $('histCtl').appendChild(segc(Object.keys(P).map(k=>[k,P[k][1]]),S.bg,v=>{S.bg=v;draw();}));\n $('histCtl').appendChild(sld('B\u00f9 tr\u1eeb ph\u01a1i s\u00e1ng',-3,3,1\/3,0,v=>(v>0?'+':v<0?'\u2212':'')+Math.abs(v).toFixed(1)+' EV',v=>{S.ev=v;draw();},1));\n const W=720,H=960;cv.width=W;cv.height=H;const off=document.createElement('canvas');off.width=W;off.height=H;const o=ctx2d(off);\n function measure(k){if(avg[k]!=null||!o||!imgReady(imgs[k]))return;o.clearRect(0,0,W,H);o.drawImage(imgs[k],0,0,W,H);const r=histogramOf(o,W,H,6);if(!r){avg[k]=.45;return;}let s=0,c=0;r.h.forEach((v,i)=>{s+=v*i;c+=v;});avg[k]=Math.max(.03,s\/Math.max(1,c)\/255);}\n const SL={white:'meter_white',blue:'meter_mid',black:'meter_dark'};Object.keys(P).forEach(k=>{simImg(SL[k],P[k][0],im=>{imgs[k]=im;avg[k]=null;measure(k);if(S.bg===k)draw();});});\n function draw(){const v=$('histVer');const im=imgs[S.bg];if(!ctx||!v||!document.body.contains(cv))return;ctx.fillStyle='#0b0f1a';ctx.fillRect(0,0,W,H);if(!imgReady(im)){v.className='verdict';v.textContent='\u0110ang t\u1ea3i \u1ea3nh\u2026';return;}measure(S.bg);\n  const auto=0.42\/avg[S.bg];const ideal=-2.2*Math.log2(auto);const f=auto*Math.pow(2,S.ev\/2.2);ctx.save();ctx.filter='brightness('+f.toFixed(3)+')';ctx.drawImage(im,0,0,W,H);ctx.restore();\n  const res=histogramOf(ctx,W,H,2);if(res&&res.img){const d=res.img;const p=d.data;for(let i=0;i<p.length;i+=4){if(p[i]>=252&&p[i+1]>=252&&p[i+2]>=252){p[i]=255;p[i+1]=60;p[i+2]=60;}else if(p[i]+p[i+1]+p[i+2]<=10){p[i]=60;p[i+1]=110;p[i+2]=255;}}ctx.putImageData(d,0,0);}\n  drawHist($('histCv'),res);const offEV=S.ev-ideal;const clip=res?' Ch\u00e1y s\u00e1ng '+(res.hi*100).toFixed(1)+'%, ch\u1ebft \u0111en '+(res.lo*100).toFixed(1)+'%.':'';\n  if(Math.abs(offEV)<0.4){v.className='verdict ok';v.textContent='Kh\u1edbp v\u1edbi \u1ea3nh g\u1ed1c \u2014 \u0111\u00e2y l\u00e0 m\u1ee9c ph\u01a1i s\u00e1ng \u0111\u00fang.'+clip;}\n  else if(offEV<0){v.className='verdict under';v.textContent='T\u1ed1i h\u01a1n \u1ea3nh g\u1ed1c '+(-offEV).toFixed(1)+' EV'+(S.ev===0&&S.bg==='white'?' \u2014 m\u00e1y \u0111o s\u00e1ng k\u00e9o ph\u00f4ng tr\u1eafng v\u1ec1 x\u00e1m.':'.')+' B\u00f9 th\u00eam +'+(-offEV).toFixed(1)+' EV.'+clip;}\n  else{v.className='verdict over';v.textContent='S\u00e1ng h\u01a1n \u1ea3nh g\u1ed1c '+offEV.toFixed(1)+' EV'+(S.ev===0&&S.bg==='black'?' \u2014 m\u00e1y \u0111o s\u00e1ng c\u1ed1 k\u00e9o n\u1ec1n t\u1ed1i l\u00ean x\u00e1m n\u00ean m\u1eb7t b\u1ecb ch\u00e1y.':'.')+' Gi\u1ea3m '+offEV.toFixed(1)+' EV.'+clip;}}\n draw();}\n\/* ---------- composition on real photos ---------- *\/\nfunction initCompo(){const cv=$('cmpCv');const ctx=ctx2d(cv);const P=[['compo_1','Ch\u00e2n dung c\u0103n gi\u1eefa','portrait'],['compo_2','Ho\u00e0ng h\u00f4n','golden'],['compo_3','To\u00e0n th\u00e2n','openshade'],['compo_4','\u0110\u01b0\u1eddng d\u1eabn','ap_deep']];const S={p:'compo_1',ov:'thirds'};const imgs={};\n $('cmpCtl').appendChild(segc(P.map(p=>[p[0],p[1]]),S.p,v=>{S.p=v;draw();}));$('cmpCtl').appendChild(segc([['none','Kh\u00f4ng l\u01b0\u1edbi'],['thirds','L\u01b0\u1edbi 1\/3'],['golden','T\u1ec9 l\u1ec7 v\u00e0ng'],['diag','\u0110\u01b0\u1eddng ch\u00e9o']],S.ov,v=>{S.ov=v;draw();}));\n P.forEach(p=>{simImg(p[0],p[2],im=>{imgs[p[0]]=im;if(S.p===p[0])draw();});});\n function draw(){if(!ctx||!document.body.contains(cv))return;const im=imgs[S.p];let W=960,H=540;if(imgReady(im)){const ar=im.naturalWidth\/im.naturalHeight;if(ar<1){W=720;H=Math.round(720\/ar);}else{W=960;H=Math.round(960\/ar);}}if(cv.width!==W)cv.width=W;if(cv.height!==H)cv.height=H;\n  ctx.fillStyle='#0b0f1a';ctx.fillRect(0,0,W,H);if(imgReady(im))ctx.drawImage(im,0,0,W,H);\n  ctx.strokeStyle='rgba(255,255,255,.85)';ctx.lineWidth=2;ctx.beginPath();if(S.ov==='thirds'){[1,2].forEach(i=>{ctx.moveTo(W*i\/3,0);ctx.lineTo(W*i\/3,H);ctx.moveTo(0,H*i\/3);ctx.lineTo(W,H*i\/3);});}\n  if(S.ov==='golden'){[0.382,0.618].forEach(r=>{ctx.moveTo(W*r,0);ctx.lineTo(W*r,H);ctx.moveTo(0,H*r);ctx.lineTo(W,H*r);});}if(S.ov==='diag'){ctx.moveTo(0,0);ctx.lineTo(W,H);ctx.moveTo(W,0);ctx.lineTo(0,H);}ctx.stroke();}\n draw();}\n\/* ---------- setups with real photos ---------- *\/\n\/* =====================================================================\n   ASSETS \u2014 photo slots & 3D characters, configurable in-app\n   ===================================================================== *\/\nconst BUILTIN_CHARS=[{id:'b_office',name:'C\u00f4ng s\u1edf',gender:'nu',outfit:'V\u00e1y c\u00f4ng s\u1edf',url:'https:\/\/kblack.vn\/wp-content\/uploads\/2026\/10\/kblack-photolab-office-v2.glb',thumb:'',height:'',rot:0,builtin:true},{id:'b_aodai',name:'\u00c1o d\u00e0i',gender:'nu',outfit:'\u00c1o d\u00e0i truy\u1ec1n th\u1ed1ng',url:'https:\/\/kblack.vn\/wp-content\/uploads\/2026\/10\/kblack-photolab-aodai-v2.glb',thumb:'',height:'',rot:0,builtin:true},{id:'b_street',name:'Streetwear',gender:'nu',outfit:'Th\u1eddi trang \u0111\u01b0\u1eddng ph\u1ed1',url:'https:\/\/kblack.vn\/wp-content\/uploads\/2026\/10\/kblack-photolab-street-v2.glb',thumb:'',height:'',rot:0,builtin:true},{id:'b_gym',name:'Th\u1ec3 thao',gender:'nu',outfit:'\u0110\u1ed3 t\u1eadp gym',url:'https:\/\/kblack.vn\/wp-content\/uploads\/2026\/10\/kblack-photolab-gym-v2.glb',thumb:'',height:'',rot:0,builtin:true},{id:'b_prince',name:'Ho\u00e0ng t\u1eed Gothic',gender:'nam',outfit:'Trang ph\u1ee5c fantasy',url:'https:\/\/kblack.vn\/wp-content\/uploads\/2026\/10\/kblack-photolab-prince-v2.glb',thumb:'',height:'',rot:0,builtin:true},{id:'b_enchant',name:'Ph\u00f9 thu\u1ef7 m\u1ea1ng che',gender:'nu',outfit:'Trang ph\u1ee5c fantasy',url:'https:\/\/kblack.vn\/wp-content\/uploads\/2026\/10\/kblack-photolab-enchant-v2.glb',thumb:'',height:'',rot:0,builtin:true},{id:'b_elf',name:'Ki\u1ebfm s\u0129 Elf',gender:'nam',outfit:'Trang ph\u1ee5c fantasy',url:'https:\/\/kblack.vn\/wp-content\/uploads\/2026\/10\/kblack-photolab-elf-v2.glb',thumb:'',height:'',rot:0,builtin:true}];\nconst DEFAULT_ASSETS={characters:[],photos:{},removed:[]};\nlet ASSETS=(()=>{try{const a=JSON.parse(localStorage.getItem('kblack_lab_assets')||'null');if(a&&Array.isArray(a.characters))return Object.assign({photos:{}},a);}catch(e){}return JSON.parse(JSON.stringify(DEFAULT_ASSETS));})();\n(function(){ASSETS.removed=ASSETS.removed||[];const have=new Set(ASSETS.characters.map(c=>c.id));const add=BUILTIN_CHARS.filter(b=>!have.has(b.id)&&ASSETS.removed.indexOf(b.id)<0).map(b=>Object.assign({},b));ASSETS.characters=add.concat(ASSETS.characters);})();(function(){var U={};BUILTIN_CHARS.forEach(function(b){U[b.id]=b.url});ASSETS.characters.forEach(function(c){if(U[c.id]&&c.url!==U[c.id])c.url=U[c.id]});})();\nfunction saveAssets(){try{localStorage.setItem('kblack_lab_assets',JSON.stringify(ASSETS));}catch(e){toast('Kh\u00f4ng l\u01b0u \u0111\u01b0\u1ee3c c\u1ea5u h\u00ecnh');}}\nconst SLOTS={\n expo_bg:{g:'Tam gi\u00e1c ph\u01a1i s\u00e1ng',t:'L\u1edbp ph\u00f4ng \u2014 kh\u00f4ng c\u00f3 ng\u01b0\u1eddi',d:'\u1ea2nh n\u1ec1n ngang 16:9, N\u00c9T to\u00e0n b\u1ed9, c\u00f3 \u0111\u00e8n v\u00e0 chi ti\u1ebft. App t\u1ef1 l\u00e0m m\u1edd theo kh\u1ea9u.',k:'xem file prompt: expo_bg'},\n expo_subject:{g:'Tam gi\u00e1c ph\u01a1i s\u00e1ng',t:'L\u1edbp ng\u01b0\u1eddi \u2014 PNG n\u1ec1n trong su\u1ed1t',d:'Ng\u01b0\u1eddi m\u1eabu n\u1eeda ng\u01b0\u1eddi, \u0111\u00e3 t\u00e1ch n\u1ec1n, lu\u00f4n n\u00e9t.',k:'xem file prompt: expo_subject'},\n expo_motion:{g:'Tam gi\u00e1c ph\u01a1i s\u00e1ng',t:'L\u1edbp v\u1eadt chuy\u1ec3n \u0111\u1ed9ng \u2014 PNG (tu\u1ef3 ch\u1ecdn)',d:'Ng\u01b0\u1eddi \u0111\u1ea1p xe ch\u1ea1y ngang, \u0111\u00e3 t\u00e1ch n\u1ec1n. T\u1ed1c ch\u1eadm s\u1ebd nho\u00e8 th\u00e0nh v\u1ec7t.',k:'xem file prompt: expo_motion'},\n ap_shallow:{g:'Kh\u1ea9u \u0111\u1ed9 & xo\u00e1 ph\u00f4ng',t:'f\/1.4 \u2014 xo\u00e1 ph\u00f4ng',d:'Ng\u01b0\u1eddi n\u00e9t, h\u00e0ng c\u00e2y v\u00e0 to\u00e0 nh\u00e0 tan th\u00e0nh m\u1ea3ng m\u00e0u. M\u1eb7t g\u1ea1ch ngay d\u01b0\u1edbi ch\u00e2n v\u1eabn n\u00e9t v\u00ec c\u00f9ng kho\u1ea3ng c\u00e1ch v\u1edbi ng\u01b0\u1eddi.',k:'shallow depth of field portrait bokeh'},\n ap_deep:{g:'Kh\u1ea9u \u0111\u1ed9 & xo\u00e1 ph\u00f4ng',t:'f\/22 \u2014 n\u00e9t ph\u00f4ng',d:'C\u00f9ng ng\u01b0\u1eddi, c\u00f9ng c\u1ea3nh: t\u1eeb m\u1eb7t g\u1ea1ch t\u1edbi to\u00e0 nh\u00e0 xa \u0111\u1ec1u n\u00e9t r\u00f5.',k:'deep depth of field portrait street'},\n sh_freeze:{g:'T\u1ed1c \u0111\u1ed9 m\u00e0n tr\u1eadp',t:'1\/2000 \u2014 \u0111\u00f3ng b\u0103ng',d:'B\u1eaft \u0111\u00fang \u0111\u1ec9nh c\u00fa nh\u1ea3y: hai ch\u00e2n r\u1eddi \u0111\u1ea5t, t\u1eebng l\u1ecdn t\u00f3c bay \u0111\u1ec1u s\u1eafc n\u00e9t.',k:'frozen motion dancer hair flying'},\n sh_blur:{g:'T\u1ed1c \u0111\u1ed9 m\u00e0n tr\u1eadp',t:'1\/15 \u2014 nho\u00e8 chuy\u1ec3n \u0111\u1ed9ng',d:'C\u00f9ng c\u00fa nh\u1ea3y, m\u00e1y tr\u00ean ch\u00e2n m\u00e1y: ng\u01b0\u1eddi nho\u00e8 th\u00e0nh v\u1ec7t theo h\u01b0\u1edbng b\u1eadt l\u00ean, ph\u00f4ng v\u00e0 b\u00f3ng s\u00e0n v\u1eabn n\u00e9t.',k:'motion blur dancer long exposure'},\n iso_low:{g:'ISO & nhi\u1ec5u',t:'ISO 100 \u2014 s\u1ea1ch',d:'Da m\u1ecbn, \u00e1o \u0111en gi\u1eef r\u00f5 \u0111\u01b0\u1eddng may v\u00e0 th\u1edb v\u1ea3i, v\u00f9ng t\u1ed1i trong. \u00d4 g\u00f3c ph\u00f3ng 200% khu\u00f4n m\u1eb7t.',k:'low light portrait clean'},\n iso_high:{g:'ISO & nhi\u1ec5u',t:'ISO 12800 \u2014 nhi\u1ec5u',d:'C\u00f9ng c\u1ea3nh khi thi\u1ebfu s\u00e1ng ph\u1ea3i \u0111\u1ea9y ISO: h\u1ea1t l\u1ea5m t\u1ea5m kh\u1eafp \u1ea3nh, \u0111\u1ed1m m\u00e0u loang tr\u00ean \u00e1o \u0111en, da \u0111\u1ee5c, m\u1ea5t chi ti\u1ebft v\u1ea3i.',k:'high iso noise grain photo'},\n focal_wide:{g:'Ti\u00eau c\u1ef1 & g\u00f3c nh\u00ecn',t:'24mm \u0111\u1ee9ng g\u1ea7n',d:'C\u00f9ng khu\u00f4n m\u1eb7t c\u00f9ng c\u1ee1 khung; m\u0169i to, tai nh\u1ecf, h\u1eadu c\u1ea3nh r\u1ed9ng v\u00e0 xa.',k:'wide angle close portrait distortion'},\n focal_tele:{g:'Ti\u00eau c\u1ef1 & g\u00f3c nh\u00ecn',t:'135mm \u0111\u1ee9ng xa',d:'C\u00f9ng khu\u00f4n m\u1eb7t; t\u1ec9 l\u1ec7 m\u1eb7t \u0111\u1eb9p, h\u1eadu c\u1ea3nh b\u1ecb n\u00e9n s\u00e1t sau l\u01b0ng.',k:'telephoto portrait background compression'},\n wb_warm:{g:'Nhi\u1ec7t \u0111\u1ed9 m\u00e0u',t:'Sai c\u00e2n b\u1eb1ng tr\u1eafng \u2014 \u00e1m cam',d:'Ch\u1ee5p d\u01b0\u1edbi \u0111\u00e8n s\u1ee3i \u0111\u1ed1t nh\u01b0ng \u0111\u1ec3 WB Daylight: ph\u00f4ng tr\u1eafng th\u00e0nh kem cam, mi\u1ebfng patch tr\u1eafng ng\u1ea3 v\u00e0ng, da \u00e1m cam.',k:'tungsten light portrait orange cast'},\n wb_ok:{g:'Nhi\u1ec7t \u0111\u1ed9 m\u00e0u',t:'\u0110\u00fang c\u00e2n b\u1eb1ng tr\u1eafng',d:'C\u00f9ng c\u1ea3nh, \u0111\u1eb7t WB kh\u1edbp ngu\u1ed3n s\u00e1ng: ph\u00f4ng v\u00e0 patch tr\u1eafng s\u1ea1ch, da v\u1ec1 m\u00e0u th\u1eadt.',k:'neutral white balance portrait indoor'},\n expo_portrait:{g:'Tam gi\u00e1c ph\u01a1i s\u00e1ng',t:'(D\u1ef1 ph\u00f2ng) M\u1ed9t \u1ea3nh ch\u00e2n dung ngang',d:'M\u1ed9t ng\u01b0\u1eddi \u0111\u1ee9ng gi\u1eefa khung, ph\u00f4ng studio c\u00f3 chi ti\u1ebft ph\u00eda sau (\u0111\u00e8n, r\u00e8m) \u0111\u1ec3 th\u1ea5y r\u00f5 xo\u00e1 ph\u00f4ng. \u1ea2nh ngang 16:9.',k:'studio portrait woman dark background, softbox behind'},\n meter_white:{g:'\u0110o s\u00e1ng & histogram',t:'Ng\u01b0\u1eddi tr\u00ean n\u1ec1n tr\u1eafng',d:'Ch\u00e2n dung ho\u1eb7c \u1ea3nh th\u1ebb n\u1ec1n tr\u1eafng tinh, ph\u01a1i s\u00e1ng chu\u1ea9n.',k:'headshot white background, portrait white backdrop'},\n meter_mid:{g:'\u0110o s\u00e1ng & histogram',t:'N\u1ec1n trung t\u00ednh',d:'Ch\u00e2n dung n\u1ec1n c\u00e2y xanh xo\u00e1 ph\u00f4ng, \u0111\u1ed9 s\u00e1ng trung b\u00ecnh.',k:'portrait green bokeh background'},\n meter_dark:{g:'\u0110o s\u00e1ng & histogram',t:'C\u1ea3nh t\u1ed1i',d:'Ng\u01b0\u1eddi \u0111\u1ee9ng trong kh\u00e1n ph\u00f2ng t\u1ed1i, n\u1ec1n g\u1ea7n nh\u01b0 \u0111en.',k:'dark event hall portrait'},\n compo_1:{g:'B\u1ed1 c\u1ee5c',t:'Ch\u00e2n dung c\u0103n gi\u1eefa',d:'M\u1eaft n\u1eb1m g\u1ea7n \u0111\u01b0\u1eddng 1\/3 ph\u00eda tr\u00ean.',k:'centered portrait'},\n compo_2:{g:'B\u1ed1 c\u1ee5c',t:'Ho\u00e0ng h\u00f4n',d:'\u0110\u01b0\u1eddng ch\u00e2n tr\u1eddi v\u00e0 m\u1eb7t tr\u1eddi trong khung.',k:'golden hour portrait horizon'},\n compo_3:{g:'B\u1ed1 c\u1ee5c',t:'To\u00e0n th\u00e2n',d:'Ng\u01b0\u1eddi \u0111\u1ee9ng to\u00e0n th\u00e2n, h\u1eadu c\u1ea3nh c\u00f3 c\u00e2y v\u00e0 to\u00e0 nh\u00e0.',k:'full body portrait outdoor'},\n compo_4:{g:'B\u1ed1 c\u1ee5c',t:'\u0110\u01b0\u1eddng d\u1eabn',d:'L\u1ed1i \u0111i, h\u00e0ng c\u00e2y, c\u1ed9t \u0111\u00e8n h\u1ed9i t\u1ee5 v\u1ec1 m\u1ed9t \u0111i\u1ec3m ph\u00eda sau ng\u01b0\u1eddi.',k:'leading lines promenade'},\n light_hard:{g:'\u00c1nh s\u00e1ng c\u1ee9ng & m\u1ec1m',t:'\u00c1nh s\u00e1ng c\u1ee9ng',d:'M\u1ed9t \u0111\u00e8n nh\u1ecf kh\u00f4ng t\u1ea3n s\u00e1ng: b\u00f3ng \u0111\u1ea7u v\u00e0 vai in s\u1eafc n\u00e9t l\u00ean t\u01b0\u1eddng ph\u00eda sau.',k:'hard light portrait strong shadows'},\n light_soft:{g:'\u00c1nh s\u00e1ng c\u1ee9ng & m\u1ec1m',t:'\u00c1nh s\u00e1ng m\u1ec1m',d:'C\u00f9ng ng\u01b0\u1eddi, c\u00f9ng ch\u1ed7 \u0111\u1ee9ng, \u0111\u1ed5i sang ngu\u1ed3n s\u00e1ng l\u1edbn: b\u00f3ng tr\u00ean t\u01b0\u1eddng loang r\u1ed9ng v\u00e0 nh\u1ea1t, kh\u00f4ng c\u00f2n vi\u1ec1n s\u1eafc.',k:'soft light portrait window light'},\n light_back:{g:'\u00c1nh s\u00e1ng c\u1ee9ng & m\u1ec1m',t:'Ng\u01b0\u1ee3c s\u00e1ng, vi\u1ec1n s\u00e1ng',d:'Ng\u01b0\u1eddi \u0111\u1ee9ng tr\u01b0\u1edbc ngu\u1ed3n s\u00e1ng, t\u00f3c v\u00e0 vai s\u00e1ng vi\u1ec1n.',k:'backlit portrait rim light'},\n nat_sun:{g:'\u00c1nh s\u00e1ng t\u1ef1 nhi\u00ean',t:'Gi\u1edd v\u00e0ng',d:'Ch\u00e2n dung ngo\u00e0i tr\u1eddi l\u00fac ho\u00e0ng h\u00f4n, n\u1eafng \u1ea5m, th\u1ea5p.',k:'golden hour portrait'},\n nat_shade:{g:'\u00c1nh s\u00e1ng t\u1ef1 nhi\u00ean',t:'B\u00f3ng r\u00e2m m\u1edf',d:'Ch\u00e2n dung ngo\u00e0i tr\u1eddi trong b\u00f3ng r\u00e2m, s\u00e1ng m\u1ec1m \u0111\u1ec1u.',k:'open shade portrait outdoor'},\n pose_1:{g:'T\u1ea1o d\u00e1ng',t:'D\u00e1ng doanh nh\u00e2n khoanh tay',d:'Nam ho\u1eb7c n\u1eef m\u1eb7c vest, khoanh tay h\u1edd, ng\u01b0\u1eddi h\u01a1i nghi\u00eang v\u1ec1 tr\u01b0\u1edbc.',k:'business portrait arms crossed'},\n pose_2:{g:'T\u1ea1o d\u00e1ng',t:'Vai xoay, c\u1eb1m \u0111\u01b0a ra tr\u01b0\u1edbc',d:'Ch\u00e2n dung n\u1eeda ng\u01b0\u1eddi, vai xoay 45\u00b0, m\u1eb7t quay l\u1ea1i m\u00e1y.',k:'corporate headshot shoulders angled'},\n pose_3:{g:'T\u1ea1o d\u00e1ng',t:'D\u00e1ng ng\u1ed3i',d:'Ng\u01b0\u1eddi ng\u1ed3i gh\u1ebf, ng\u01b0\u1eddi h\u01a1i nghi\u00eang v\u1ec1 tr\u01b0\u1edbc, tay \u0111\u1eb7t t\u1ef1 nhi\u00ean.',k:'seated portrait pose studio'},\n pose_group:{g:'T\u1ea1o d\u00e1ng',t:'Nh\u00f3m x\u1ebfp tam gi\u00e1c',d:'Nh\u00f3m nh\u1ecf 4\u20138 ng\u01b0\u1eddi, \u0111\u1ea7u so le, kh\u00f4ng th\u1eb3ng h\u00e0ng.',k:'small team portrait staggered'},\n studio_hero:{g:'S\u01a1 \u0111\u1ed3 \u0111\u00e8n',t:'Studio c\u00f3 \u0111\u00e8n',d:'To\u00e0n c\u1ea3nh m\u1ed9t studio ch\u1ee5p \u1ea3nh c\u00f3 softbox, ch\u00e2n \u0111\u00e8n, ph\u00f4ng.',k:'photo studio lighting equipment'},\n session_hero:{g:'Quy tr\u00ecnh bu\u1ed5i ch\u1ee5p',t:'H\u1eadu tr\u01b0\u1eddng bu\u1ed5i ch\u1ee5p',d:'Nhi\u1ebfp \u1ea3nh gia \u0111ang ch\u1ee5p, c\u00f3 ekip v\u00e0 \u0111\u00e8n.',k:'photographer behind the scenes studio'},\n workflow_hero:{g:'RAW & tether',t:'Ch\u1ee5p tether',d:'M\u00e1y \u1ea3nh n\u1ed1i laptop, \u1ea3nh hi\u1ec7n tr\u00ean m\u00e0n h\u00ecnh l\u1edbn.',k:'tethered shooting laptop photographer'}};\nconst SETUP_KW={rembrandt:'rembrandt lighting portrait',loop:'loop lighting portrait',butterfly:'butterfly lighting beauty portrait',split:'split lighting portrait',clamshell:'clamshell lighting beauty',three:'three point lighting interview',boom:'top light portrait dramatic',highkey:'high key portrait white background',lowkey:'low key portrait black background',group:'group photo studio lighting',colorbg:'colored gel backdrop portrait',product:'cosmetic bottle product photography'};\nObject.keys(SETUP_TXT).forEach(k=>{SLOTS['setup_'+k]={g:'S\u01a1 \u0111\u1ed3 \u0111\u00e8n',t:'V\u00ed d\u1ee5 '+SETUP_TXT[k][0],d:'\u1ea2nh ch\u1ee5p \u0111\u00fang ki\u1ec3u '+SETUP_TXT[k][0]+'.',k:SETUP_KW[k]||''};});\nconst SLOT_DEFAULT={wb_warm:'wb_warm',wb_ok:'wb_ok',light_soft:'light_soft',sh_freeze:'sh_freeze',sh_blur:'sh_blur',light_hard:'light_hard',pose_2:'pose_2',setup_clamshell:'setup_clamshell',setup_lowkey:'setup_lowkey',ap_shallow:'ap_shallow',ap_deep:'ap_deep',iso_low:'iso_low',iso_high:'iso_high',focal_wide:'focal_wide',focal_tele:'focal_tele',meter_white:'white',meter_mid:'portrait',meter_dark:'dark_event',nat_sun:'golden',nat_shade:'openshade',compo_1:'portrait',compo_2:'golden',compo_3:'openshade',compo_4:'ap_deep'};\nfunction slotURL(id){return (ASSETS.photos||{})[id]||(SLOT_DEFAULT[id]?ph(SLOT_DEFAULT[id]):'');}\nfunction renderFigures(root){root.querySelectorAll('figure[data-slot]').forEach(f=>{const id=f.dataset.slot;const s=SLOTS[id];if(!s)return;const u=slotURL(id);if(!u){f.remove();return;}\n f.innerHTML=u?'<img alt=\"PHOTO LAB \u2013 K-BLACK Studio\" decoding=\"async\" src=\"'+u+'\" alt=\"'+s.t+'\" loading=\"lazy\"><figcaption><b>'+s.t+'.<\/b> '+s.d+'<\/figcaption>':'<div class=\"phbox\"><b>'+s.t+'<\/b><span>'+s.d+'<\/span><small>T\u1eeb kho\u00e1 t\u00ecm: '+s.k+'<\/small><button class=\"gbtn\" data-slot-open=\"'+id+'\">D\u00e1n link \u1ea3nh<\/button><\/div>';});\n root.querySelectorAll('.figrow').forEach(r=>{if(!r.querySelector('figure'))r.remove();else if(r.querySelectorAll('figure').length===1)r.classList.add('one');});root.querySelectorAll('h2.figh').forEach(h=>{let n=h.nextElementSibling;if(!n||!(n.matches('.figrow,figure')))h.remove();});root.querySelectorAll('[data-slot-open]').forEach(b=>b.onclick=()=>openAssets('photos',b.dataset.slotOpen));}\nfunction simImg(slot,fallbackKey,cb){const u=slotURL(slot);const fb=()=>{const f=new Image();f.onload=()=>cb(f);f.src=ph(fallbackKey);};if(!u){fb();return;}const im=new Image();im.crossOrigin='anonymous';im.onload=()=>cb(im);im.onerror=fb;im.src=u;}\n\/* ---------- characters ---------- *\/\nconst CHAR_CACHE={};const MIXERS=[];\nfunction charById(id){return ASSETS.characters.find(c=>c.id===id)||null;}\nfunction charH(c){return c?(+c.height||(c.gender==='nu'?1.65:1.75)):1.72;}\nfunction subjChars(){const s=ST.subj.char;const ok=ASSETS.characters.filter(c=>c.url);if(s==='all')return ok;const c=charById(s);if(c&&c.url)return [c];return ok.length?[ok[0]]:[];}\nfunction subjH(){const cs=subjChars();return cs.length?charH(cs[0]):1.72;}\nfunction charAvatar(c){if(c&&c.thumb)return '<img alt=\"PHOTO LAB \u2013 K-BLACK Studio\" decoding=\"async\" src=\"'+c.thumb+'\">';const col=!c?'#5d6985':c.gender==='nu'?'#ff7a9c':'#7aa2ff';return '<svg viewBox=\"0 0 40 40\" width=\"100%\" height=\"100%\"><circle cx=\"20\" cy=\"13\" r=\"7\" fill=\"'+col+'\"\/><path d=\"M6 38c1-9 7-14 14-14s13 5 14 14z\" fill=\"'+col+'\"\/><\/svg>';}\nfunction loadChar(c,cb,quiet){if(!c||!c.url||typeof THREE==='undefined')return;const e=CHAR_CACHE[c.url];if(e){if(e.status==='ok')cb&&cb(e);else if(e.status==='loading')e.cbs.push(cb);return;}\n if(!THREE.GLTFLoader){toast('Ch\u01b0a t\u1ea3i \u0111\u01b0\u1ee3c b\u1ed9 \u0111\u1ecdc model 3D \u2014 ki\u1ec3m tra m\u1ea1ng');return;}const ent={status:'loading',cbs:[cb]};CHAR_CACHE[c.url]=ent;\n const ld=new THREE.GLTFLoader();if(THREE.DRACOLoader){if(!window._draco){window._draco=new THREE.DRACOLoader();window._draco.setDecoderPath('https:\/\/www.gstatic.com\/draco\/versioned\/decoders\/1.4.1\/');}ld.setDRACOLoader(window._draco);}\n let lastP=0;if(!quiet)toast('\u0110ang t\u1ea3i \"'+c.name+'\"\u2026');refreshCharList();\n ld.load(c.url,gl=>{const sc=gl.scene;sc.updateMatrixWorld(true);ent.box=new THREE.Box3().setFromObject(sc);ent.scene=sc;ent.anims=gl.animations||[];ent.autoRot=autoFace(sc,ent.box);ent.status='ok';\n  sc.traverse(o=>{if(o.isMesh){o.castShadow=true;o.receiveShadow=true;o.frustumCulled=false;(Array.isArray(o.material)?o.material:[o.material]).forEach(m=>{if(m&&m.map)m.map.encoding=THREE.sRGBEncoding;if(m&&m.emissiveMap)m.emissiveMap.encoding=THREE.sRGBEncoding;});}});\n  if(!getThumb(c))makeThumb(c,ent);const cbs=ent.cbs;ent.cbs=[];cbs.forEach(f=>f&&f(ent));refreshCharList();if(!quiet)toast('\u0110\u00e3 t\u1ea3i \"'+c.name+'\"');},\n  p=>{if(p&&p.total){ent.prog=p.loaded\/p.total;const k=Math.floor(p.loaded\/p.total*10);if(k>lastP){lastP=k;refreshCharList();if(!quiet)toast('\u0110ang t\u1ea3i \"'+c.name+'\" \u2014 '+k*10+'% ('+(p.total\/1048576).toFixed(1)+' MB)');}}},\n  err=>{ent.status='err';refreshCharList();if(quiet)return;const cors=location.protocol==='file:'||(c.url.indexOf(location.host)<0&&\/^https?:\/.test(c.url));toast(cors?'Tr\u00ecnh duy\u1ec7t ch\u1eb7n t\u1ea3i \"'+c.name+'\" t\u1eeb t\u00ean mi\u1ec1n kh\u00e1c \u2014 m\u1edf app ngay tr\u00ean kblack.vn, ho\u1eb7c b\u1eadt CORS (xem h\u01b0\u1edbng d\u1eabn)':'Kh\u00f4ng t\u1ea3i \u0111\u01b0\u1ee3c \"'+c.name+'\" \u2014 ki\u1ec3m tra link');});}\nfunction autoFace(sc,box){try{const sz=new THREE.Vector3();box.getSize(sz);const lim=box.min.y+sz.y*0.07;let fx=[1e9,-1e9],fz=[1e9,-1e9];const v=new THREE.Vector3();\n sc.traverse(o=>{if(!o.isMesh||!o.geometry||!o.geometry.attributes.position)return;const p=o.geometry.attributes.position;const step=Math.max(1,Math.floor(p.count\/40000));for(let i=0;i<p.count;i+=step){v.fromBufferAttribute(p,i).applyMatrix4(o.matrixWorld);if(v.y<lim){fx[0]=Math.min(fx[0],v.x);fx[1]=Math.max(fx[1],v.x);fz[0]=Math.min(fz[0],v.z);fz[1]=Math.max(fz[1],v.z);}}});\n const c=new THREE.Vector3();box.getCenter(c);const side=sz.z>sz.x*1.15;\n if(!side)return 0;const right=(fx[1]-c.x)>=(c.x-fx[0]);return right?-90:90;}catch(e){return 0;}}\nfunction charInstance(c,ent,animate){const inst=THREE.SkeletonUtils?THREE.SkeletonUtils.clone(ent.scene):ent.scene.clone(true);inst.traverse(o=>{if(o.isMesh){o.userData.shared=true;o.castShadow=true;o.receiveShadow=true;o.frustumCulled=false;}});\n const sz=new THREE.Vector3(),ctr=new THREE.Vector3();ent.box.getSize(sz);ent.box.getCenter(ctr);const s=charH(c)\/Math.max(1e-3,sz.y);const piv=new THREE.Group();inst.position.set(-ctr.x,-ent.box.min.y,-ctr.z);piv.add(inst);piv.scale.setScalar(s);piv.rotation.y=rad((+c.rot||0)+(ent.autoRot||0));const wrap=new THREE.Group();wrap.add(piv);\n if(animate&&ent.anims.length&&THREE.AnimationMixer){const mx=new THREE.AnimationMixer(inst);const clip=ent.anims.find(a=>\/idle|breath|stand\/i.test(a.name))||ent.anims[0];mx.clipAction(clip).play();MIXERS.push(mx);}return wrap;}\nfunction uidc(){return 'c'+Date.now().toString(36)+Math.random().toString(36).slice(2,5);}\n\/* ---------- modals: assets, characters, profile ---------- *\/\nfunction modal(id,title,body,wide){let m=$(id);if(!m){m=el('div','modal');m.id=id;document.body.appendChild(m);m.onclick=e=>{if(e.target===m)m.classList.remove('show');};}\n m.innerHTML='';const b=el('div','mbox'+(wide?' wide':''));const h=el('div','mhead','<b>'+title+'<\/b>');const x=el('button','tbtn','\u0110\u00f3ng');x.onclick=()=>m.classList.remove('show');h.appendChild(x);b.append(h,body);m.appendChild(b);m.classList.add('show');return m;}\nfunction openAssets(tab,focus){tab=tab||'chars';const body=el('div');const tabs=el('div','seg');[['chars','Nh\u00e2n v\u1eadt 3D'],['photos','\u1ea2nh b\u00e0i h\u1ecdc'],['backup','Sao l\u01b0u']].forEach(t=>{const b=el('button',t[0]===tab?'on':'',t[1]);b.onclick=()=>openAssets(t[0]);tabs.appendChild(b);});body.appendChild(tabs);const C=el('div','acont');body.appendChild(C);\n if(tab==='chars'){C.appendChild(el('p','note','D\u00e1n link file .glb (t\u1ea3i l\u00ean WordPress). App t\u1ef1 ch\u1ec9nh chi\u1ec1u cao v\u00e0 \u0111\u1eb7t ch\u00e2n ch\u1ea1m s\u00e0n. N\u1ebfu nh\u00e2n v\u1eadt quay l\u01b0ng, \u0111\u1ed5i \"H\u01b0\u1edbng m\u1eb7t\".'));\n  ASSETS.characters.forEach((c,i)=>{const r=el('div','arow');const f=(lab,key,ph,type)=>{const w=el('label','af','<span>'+lab+'<\/span>');const inp=document.createElement(type==='sel'?'select':'input');if(type==='sel'){ph.forEach(o=>{const op=document.createElement('option');op.value=o[0];op.textContent=o[1];if(String(c[key])===String(o[0]))op.selected=true;inp.appendChild(op);});}else{inp.type='text';inp.placeholder=ph;inp.value=c[key]||'';}inp.onchange=inp.oninput=()=>{c[key]=inp.value;saveAssets();};w.appendChild(inp);return w;};\n   r.append(el('div','acav',charAvatar(c)),f('T\u00ean','name','Nam vest navy'),f('Gi\u1edbi t\u00ednh','gender',[['nam','Nam'],['nu','N\u1eef']],'sel'),f('Trang ph\u1ee5c','outfit','Vest c\u00f4ng s\u1edf'),f('Link .glb','url','https:\/\/kblack.vn\/wp-content\/uploads\/\u2026\/nhan-vat.glb'),f('\u1ea2nh \u0111\u1ea1i di\u1ec7n (tu\u1ef3 ch\u1ecdn)','thumb','https:\/\/\u2026\/nhan-vat.png'),f('Chi\u1ec1u cao (m)','height',c.gender==='nu'?'1.65':'1.75'),f('H\u01b0\u1edbng m\u1eb7t (sau khi app t\u1ef1 d\u00f2)','rot',[[0,'Gi\u1eef nguy\u00ean'],[90,'Xoay th\u00eam 90\u00b0'],[180,'Xoay th\u00eam 180\u00b0'],[270,'Xoay th\u00eam 270\u00b0']],'sel'));\n   const bt=el('div','minib');const t=el('button',null,'T\u1ea3i th\u1eed');t.onclick=()=>{delete CHAR_CACHE[c.url];loadChar(c,()=>{});};const d=el('button','dg','Xo\u00e1');d.onclick=()=>{if(c.builtin){ASSETS.removed=ASSETS.removed||[];ASSETS.removed.push(c.id);}ASSETS.characters.splice(i,1);saveAssets();if(ST.subj.char===c.id){ST.subj.char='';changed();}openAssets('chars');};bt.append(t,d);r.appendChild(bt);C.appendChild(r);});\n  const add=el('button','addl','+ Th\u00eam nh\u00e2n v\u1eadt');add.onclick=()=>{ASSETS.characters.push({id:uidc(),name:'Nh\u00e2n v\u1eadt '+(ASSETS.characters.length+1),gender:'nam',outfit:'',url:'',thumb:'',height:'',rot:0});saveAssets();openAssets('chars');};C.appendChild(add);}\n if(tab==='photos'){C.appendChild(el('p','note','M\u1ed7i \u00f4 l\u00e0 m\u1ed9t \u1ea3nh minh ho\u1ea1 trong b\u00e0i h\u1ecdc. T\u1ea3i \u1ea3nh v\u1ec1, up WordPress, d\u00e1n link v\u00e0o \u0111\u00e2y. \u0110\u1ec3 tr\u1ed1ng th\u00ec b\u00e0i h\u1ecdc hi\u1ec7n khung ch\u1edd.'));let grp='';\n  Object.keys(SLOTS).forEach(id=>{const s=SLOTS[id];if(s.g!==grp){grp=s.g;C.appendChild(el('div','agrp',grp));}const r=el('div','prow'+(id===focus?' focus':''));const pv=el('div','pv',slotURL(id)?'<img alt=\"PHOTO LAB \u2013 K-BLACK Studio\" decoding=\"async\" src=\"'+slotURL(id)+'\">':'');if(!(ASSETS.photos||{})[id]&&SLOT_DEFAULT[id])pv.classList.add('def');const inf=el('div','pinf','<b>'+s.t+'<\/b><span>'+s.d+'<\/span><small>T\u1eeb kho\u00e1: '+s.k+'<\/small>');const inp=document.createElement('input');inp.type='text';inp.placeholder=SLOT_DEFAULT[id]?'\u0110ang d\u00f9ng \u1ea3nh c\u00f3 s\u1eb5n \u2014 d\u00e1n link \u0111\u1ec3 thay':'https:\/\/\u2026\/anh.jpg';inp.value=(ASSETS.photos||{})[id]||'';inp.oninput=()=>{ASSETS.photos[id]=inp.value.trim();if(!ASSETS.photos[id])delete ASSETS.photos[id];saveAssets();pv.innerHTML=inp.value?'<img alt=\"PHOTO LAB \u2013 K-BLACK Studio\" decoding=\"async\" src=\"'+inp.value+'\">':'';};inf.appendChild(inp);r.append(pv,inf);C.appendChild(r);if(id===focus)setTimeout(()=>{r.scrollIntoView&&r.scrollIntoView({block:'center'});inp.focus();},50);});}\n if(tab==='backup'){C.appendChild(el('p','note','T\u1ea3i file c\u1ea5u h\u00ecnh v\u1ec1 \u0111\u1ec3 c\u1ea5t, ho\u1eb7c n\u1ea1p l\u1ea1i tr\u00ean m\u00e1y kh\u00e1c. G\u1eedi file n\u00e0y cho ng\u01b0\u1eddi d\u1ef1ng app \u0111\u1ec3 g\u1eafn c\u1ed1 \u0111\u1ecbnh v\u00e0o code.'));const ex=el('button','pbtn','T\u1ea3i file c\u1ea5u h\u00ecnh');ex.onclick=()=>{const a=document.createElement('a');a.href=URL.createObjectURL(new Blob([JSON.stringify(ASSETS,null,1)],{type:'application\/json'}));a.download='kblack-lab-tai-nguyen.json';a.click();};\n  const im=el('button','gbtn','N\u1ea1p file c\u1ea5u h\u00ecnh');im.onclick=()=>{const i=document.createElement('input');i.type='file';i.accept='.json';i.onchange=()=>{const r=new FileReader();r.onload=()=>{try{const a=JSON.parse(r.result);if(!Array.isArray(a.characters))throw 0;ASSETS=Object.assign({photos:{}},a);saveAssets();toast('\u0110\u00e3 n\u1ea1p c\u1ea5u h\u00ecnh');openAssets('chars');}catch(e){toast('File kh\u00f4ng h\u1ee3p l\u1ec7');}};r.readAsText(i.files[0]);};i.click();};\n  const w=el('div','minib');w.append(ex,im);C.appendChild(w);}\n modal('assetsModal','T\u00e0i nguy\u00ean \u2014 nh\u00e2n v\u1eadt 3D v\u00e0 \u1ea3nh b\u00e0i h\u1ecdc',body,true);}\nfunction openChars(){const body=el('div');body.appendChild(el('p','note','Ch\u1ecdn nh\u00e2n v\u1eadt \u0111\u1ee9ng trong studio. Th\u00eam nh\u00e2n v\u1eadt m\u1edbi \u1edf m\u1ee5c T\u00e0i nguy\u00ean.'));const G=el('div','cgrid');\n const card=(id,name,sub,av,st)=>{const c=el('button','ccard'+(ST.subj.char===id?' on':''),'<span class=\"cimg\">'+av+'<\/span><b>'+name+'<\/b><small>'+sub+'<\/small>'+(st?'<em>'+st+'<\/em>':''));c.onclick=()=>{ST.subj.char=id;$('charModal').classList.remove('show');const ch=charById(id);if(ch)loadChar(ch,()=>{S3&&(S3.ss=null);DIRTY=true;updateMeter();});buildLeft();changed();};return c;};\n \n ASSETS.characters.forEach(c=>{const e=CHAR_CACHE[c.url];G.appendChild(card(c.id,c.name||'Nh\u00e2n v\u1eadt',(c.gender==='nu'?'N\u1eef':'Nam')+(c.outfit?' \u00b7 '+c.outfit:''),charAvatar(c),!c.url?'Ch\u01b0a c\u00f3 link':e&&e.status==='ok'?'\u0110\u00e3 t\u1ea3i':e&&e.status==='err'?'L\u1ed7i t\u1ea3i':''));});\n if(ASSETS.characters.length>1&&ST.subj.type==='group')G.appendChild(card('all','Xoay v\u00f2ng','M\u1ed7i ng\u01b0\u1eddi trong nh\u00f3m m\u1ed9t nh\u00e2n v\u1eadt',charAvatar({gender:'nam'})));\n body.appendChild(G);const a=el('button','addl','+ Th\u00eam nh\u00e2n v\u1eadt trong T\u00e0i nguy\u00ean');a.onclick=()=>{$('charModal').classList.remove('show');openAssets('chars');};body.appendChild(a);modal('charModal','Ch\u1ecdn nh\u00e2n v\u1eadt',body,true);}\n\/* =====================================================================\n   GAME LAYER \u2014 XP, levels, missions, badges\n   ===================================================================== *\/\nconst LEVELS=[[0,'T\u00e2n binh'],[150,'Tr\u1ee3 l\u00fd set'],[400,'Nhi\u1ebfp \u1ea3nh gia'],[800,'Chuy\u00ean gia \u00e1nh s\u00e1ng'],[1400,'Gaffer'],[2200,'\u0110\u1ea1o di\u1ec5n h\u00ecnh \u1ea3nh'],[3200,'Huy\u1ec1n tho\u1ea1i K-BLACK']];\nlet GAME=(()=>{try{const g=JSON.parse(localStorage.getItem('kblack_lab_game')||'null');if(g&&g.xp!=null)return Object.assign({done:{},lessons:{},cur:'m_meter',quizBest:0},g);}catch(e){}return {xp:0,done:{},lessons:{},cur:'m_meter',quizBest:0};})();\nlet USER_ACTED=false;\nfunction saveGame(){try{localStorage.setItem('kblack_lab_game',JSON.stringify(GAME));}catch(e){}}\nfunction lvlOf(x){let i=0;LEVELS.forEach((l,k)=>{if(x>=l[0])i=k;});return i;}\nfunction updPlayer(){const i=lvlOf(GAME.xp);const cur=LEVELS[i][0],nx=LEVELS[i+1]?LEVELS[i+1][0]:cur;const p=nx>cur?(GAME.xp-cur)\/(nx-cur):1;if($('pLv'))$('pLv').textContent=i+1;if($('pName'))$('pName').textContent=LEVELS[i][1];if($('pXpTxt'))$('pXpTxt').textContent=GAME.xp+(nx>cur?' \/ '+nx:'')+' XP';if($('pXp'))$('pXp').style.width=Math.round(p*100)+'%';}\nfunction addXP(n,why){if(!n)return;const b=lvlOf(GAME.xp);GAME.xp+=n;saveGame();updPlayer();const f=el('div','xpfly','+'+n+' XP<small>'+(why||'')+'<\/small>');document.body.appendChild(f);setTimeout(()=>f.remove(),2200);const a=lvlOf(GAME.xp);if(a>b)levelUp(a);}\nfunction levelUp(i){confetti();const b=el('div','lvup','<small>L\u00caN C\u1ea4P '+(i+1)+'<\/small><b>'+LEVELS[i][1]+'<\/b>');document.body.appendChild(b);setTimeout(()=>b.remove(),2800);}\nfunction confetti(){const cols=['#ffb259','#7aa2ff','#ff7a9c','#5ee0a0','#c89bff','#ffffff'];const box=el('div','confetti');for(let i=0;i<70;i++){const s=el('i');s.style.left=Math.random()*100+'%';s.style.background=cols[i%cols.length];s.style.animationDelay=(Math.random()*.4)+'s';s.style.animationDuration=(1.6+Math.random()*1.2)+'s';s.style.transform='rotate('+Math.random()*360+'deg)';box.appendChild(s);}document.body.appendChild(box);setTimeout(()=>box.remove(),3200);}\nfunction awardLesson(ls){if(GAME.lessons[ls.id])return;GAME.lessons[ls.id]=1;addXP(40,'Ho\u00e0n th\u00e0nh b\u00e0i: '+ls.t);}\nconst keyL=()=>ST.lights.filter(L=>L.on&&L.role==='key').sort((a,b)=>b.power-a.power)[0];\nfunction ratioKF(M){let k=0,f=0;ST.lights.forEach((L,i)=>{const p=M.per[i];if(!p)return;if(L.role==='key')k=Math.max(k,p.inc);if(L.role==='fill')f=Math.max(f,p.inc);});return f>0?k\/f:Infinity;}\nconst expOK=M=>Math.abs(M.ev)<0.5;\nconst MISSIONS=[\n {id:'m_meter',ic:'\u25ce',t:'Ph\u01a1i s\u00e1ng chu\u1ea9n',d:'\u0110\u01b0a m\u00e1y \u0111o v\u1ec1 v\u00f9ng xanh.',hint:'B\u1ea5m \"\u0110\u1eb7t kh\u1ea9u theo \u0111\u1ec1 xu\u1ea5t\" tr\u00ean m\u00e1y \u0111o, ho\u1eb7c ch\u1ec9nh c\u00f4ng su\u1ea5t \u0111\u00e8n ch\u00ednh.',goals:[['L\u1ec7ch s\u00e1ng trong \u00b1\u2153 EV',M=>Math.abs(M.ev)<0.34]]},\n {id:'m_rembrandt',ic:'\u25d0',t:'Tam gi\u00e1c Rembrandt',d:'D\u1ef1ng ki\u1ec3u Rembrandt kinh \u0111i\u1ec3n v\u1edbi t\u1ec9 l\u1ec7 s\u00e1ng c\u00f3 ch\u1ee7 \u00fd.',hint:'Key l\u1ec7ch 40\u201350\u00b0, cao h\u01a1n m\u1eb7t kho\u1ea3ng n\u1eeda m\u00e9t. Fill ph\u00eda \u0111\u1ed1i di\u1ec7n, y\u1ebfu h\u01a1n 1\u20132 stop.',goals:[['C\u00f3 \u0111\u00e8n Key \u0111ang b\u1eadt',()=>!!keyL()],['Key l\u1ec7ch 35\u00b0\u201360\u00b0',()=>{const k=keyL();const a=k?Math.abs(wrapAz(k.az)):0;return a>=35&&a<=60;}],['Key cao h\u01a1n m\u1eb7t 0,3\u20130,9 m',()=>{const k=keyL();const d=k?k.height-geo().faceY:0;return d>=0.3&&d<=0.9;}],['T\u1ec9 l\u1ec7 Key : Fill t\u1eeb 2:1 \u0111\u1ebfn 4:1',M=>{const r=ratioKF(M);return r>=2&&r<=4;}],['Ph\u01a1i s\u00e1ng \u0111\u00fang \u00b1\u00bd EV',expOK]]},\n {id:'m_rim',ic:'\u25d1',t:'T\u00e1ch n\u1ec1n b\u1eb1ng \u0111\u00e8n vi\u1ec1n',d:'L\u00e0m vai v\u00e0 t\u00f3c s\u00e1ng vi\u1ec1n, t\u00e1ch kh\u1ecfi ph\u00f4ng t\u1ed1i.',hint:'Th\u00eam \u0111\u00e8n vai tr\u00f2 Rim \u2014 app t\u1ef1 \u0111\u1eb7t sau l\u01b0ng. Ch\u1ecdn ph\u00f4ng t\u1ed1i.',goals:[['C\u00f3 \u0111\u00e8n Rim \u0111ang b\u1eadt',()=>ST.lights.some(L=>L.on&&L.role==='rim')],['Rim \u1edf sau l\u01b0ng, g\u00f3c 120\u00b0\u2013170\u00b0',()=>ST.lights.some(L=>{const a=Math.abs(wrapAz(L.az));return L.on&&L.role==='rim'&&a>=120&&a<=170;})],['Ph\u00f4ng t\u1ed1i: x\u00e1m, navy ho\u1eb7c \u0111en',()=>ST.bd.on&&lum(ST.bd.color)<0.35],['Ph\u01a1i s\u00e1ng \u0111\u00fang \u00b1\u00bd EV',expOK]]},\n {id:'m_lowkey',ic:'\u25cf',t:'Low-key \u0111i\u1ec7n \u1ea3nh',d:'N\u1ec1n ch\u00ecm trong \u0111en, ch\u1ec9 khu\u00f4n m\u1eb7t \u0111\u01b0\u1ee3c chi\u1ebfu s\u00e1ng.',hint:'Ph\u00f4ng \u0111en, t\u01b0\u1eddng \u0111en, strip c\u00f3 t\u1ed5 ong, t\u1eaft fill v\u00e0 \u0111\u00e8n ph\u00f2ng.',goals:[['Ph\u00f4ng \u0111en ho\u1eb7c g\u1ea7n \u0111en',()=>ST.bd.on&&lum(ST.bd.color)<0.02],['T\u01b0\u1eddng \u0111en ho\u1eb7c g\u1ea1ch m\u1ed9c',()=>ST.room.wall==='black'||ST.room.wall==='brick'],['\u0110\u00e8n Key g\u1eafn t\u1ed5 ong',()=>{const k=keyL();return !!(k&&k.grid);}],['Kh\u00f4ng d\u00f9ng \u0111\u00e8n Fill',()=>!ST.lights.some(L=>L.on&&L.role==='fill')],['\u00c1nh s\u00e1ng ph\u00f2ng \u2264 20 lux',()=>ST.room.ambient<=20],['Ph\u01a1i s\u00e1ng \u0111\u00fang \u00b1\u00bd EV',expOK]]},\n {id:'m_highkey',ic:'\u25cb',t:'High-key n\u1ec1n tr\u1eafng',d:'N\u1ec1n tr\u1eafng tinh, ng\u01b0\u1eddi s\u00e1ng \u0111\u1ec1u.',hint:'Ph\u00f4ng tr\u1eafng, ng\u01b0\u1eddi c\u00e1ch ph\u00f4ng \u00edt nh\u1ea5t 1,5 m, th\u00eam \u0111\u00e8n vai tr\u00f2 N\u1ec1n.',goals:[['Ph\u00f4ng tr\u1eafng ho\u1eb7c r\u1ea5t s\u00e1ng',()=>ST.bd.on&&lum(ST.bd.color)>0.75],['C\u00f3 \u0111\u00e8n chi\u1ebfu v\u00e0o ph\u00f4ng',()=>ST.lights.some(L=>L.on&&L.aim==='bg')],['Ng\u01b0\u1eddi c\u00e1ch ph\u00f4ng \u2265 1,5 m',()=>ST.subj.bd>=1.5],['Ph\u01a1i s\u00e1ng \u0111\u00fang \u00b1\u00bd EV',expOK]]},\n {id:'m_boom',ic:'\u25bc',t:'Treo \u0111\u00e8n \u0111\u1ec9nh b\u1eb1ng boom',d:'\u0110\u00e8n r\u1ecdi t\u1eeb tr\u00ean \u0111\u1ea7u m\u00e0 ch\u00e2n \u0111\u00e8n kh\u00f4ng l\u1ecdt khung.',hint:'Th\u00eam \u0111\u00e8n vai tr\u00f2 \u0110\u1ec9nh ho\u1eb7c b\u1eadt Ch\u00e2n boom cho m\u1ed9t \u0111\u00e8n.',goals:[['C\u00f3 \u0111\u00e8n \u0111ang b\u1eadt d\u00f9ng ch\u00e2n boom',()=>ST.lights.some(L=>L.on&&L.boom)],['\u0110\u00e8n boom cao h\u01a1n \u0111\u1ea7u \u2265 0,5 m',()=>ST.lights.some(L=>L.on&&L.boom&&L.height-geo().faceY>=0.5)],['\u0110\u00e8n boom g\u1ea7n tr\u1ee5c \u0111\u1ea7u (\u2264 0,8 m)',()=>ST.lights.some(L=>L.on&&L.boom&&L.dist<=0.8)],['Kh\u00f4ng c\u00f3 c\u1ea3nh b\u00e1o ch\u00e2n \u0111\u00e8n',()=>!warnings().some(w=>\/ch\u00e2n \u0111\u00e8n\/.test(w))]]},\n {id:'m_group',ic:'\u2042',t:'Nh\u00f3m 12 ng\u01b0\u1eddi \u0111\u1ec1u s\u00e1ng',d:'Ng\u01b0\u1eddi \u0111\u1ee9ng r\u00eca v\u00e0 \u0111\u1ee9ng gi\u1eefa s\u00e1ng nh\u01b0 nhau.',hint:'Hai d\u00f9 l\u1edbn \u0111\u1eb7t xa, ch\u00e9o hai b\u00ean m\u00e1y, n\u00e2ng cao. Ho\u1eb7c m\u1edf setup m\u1eabu Ch\u1ee5p nh\u00f3m r\u1ed3i tinh ch\u1ec9nh.',goals:[['Ch\u1ebf \u0111\u1ed9 nh\u00f3m, \u00edt nh\u1ea5t 12 ng\u01b0\u1eddi',()=>ST.subj.type==='group'&&ST.subj.count>=12],['Ch\u00eanh s\u00e1ng trong nh\u00f3m \u2264 0,7 stop',M=>!!M.grp&&M.grp.spread<=0.7],['Khung l\u1ea5y h\u1ebft nh\u00f3m',()=>!warnings().some(w=>\/Khung ch\u01b0a\/.test(w))],['Ph\u01a1i s\u00e1ng \u0111\u00fang \u00b1\u00bd EV',expOK]]},\n {id:'m_flash',ic:'\u26a1',t:'L\u00e0m ch\u1ee7 flash',d:'Ch\u1ee5p flash \u0111\u00fang t\u1ed1c \u0111\u1ed3ng b\u1ed9, ISO g\u1ed1c.',hint:'Chuy\u1ec3n m\u1ecdi \u0111\u00e8n sang Flash, \u0111\u1eb7t t\u1ed1c 1\/160\u20131\/250, ISO 100 r\u1ed3i b\u1ea5m \u0110\u1eb7t kh\u1ea9u theo \u0111\u1ec1 xu\u1ea5t.',goals:[['M\u1ecdi \u0111\u00e8n \u0111ang b\u1eadt l\u00e0 flash',()=>ST.lights.some(L=>L.on)&&ST.lights.every(L=>!L.on||L.kind==='flash')],['T\u1ed1c kh\u00f4ng v\u01b0\u1ee3t 1\/250',()=>ST.cam.t>=1\/250],['ISO 100',()=>ST.cam.ISO===100],['Ph\u01a1i s\u00e1ng \u0111\u00fang \u00b1\u00bd EV',expOK]]}];\nfunction missionBox(){const box=el('div','grp mis');box.id='misBox';return box;}\nfunction updateMissions(M){const box=$('misBox');const m=MISSIONS.find(x=>x.id===GAME.cur)||MISSIONS[0];M=M||meter();const res=m.goals.map(gl=>{try{return !!gl[1](M);}catch(e){return false;}});const ok=res.filter(Boolean).length;const all=ok===res.length;\n if(all&&USER_ACTED&&!GAME.done[m.id]){GAME.done[m.id]=Date.now();saveGame();confetti();addXP(120,'Nhi\u1ec7m v\u1ee5: '+m.t);}\n if(!box)return;const done=!!GAME.done[m.id];box.innerHTML='';const hd=el('h4',null,'Nhi\u1ec7m v\u1ee5 <small>'+Object.keys(GAME.done).length+'\/'+MISSIONS.length+' ho\u00e0n th\u00e0nh<\/small>');box.appendChild(hd);\n const sel=el('div','mchips');MISSIONS.forEach(x=>{const c=el('button','mchip'+(x.id===m.id?' on':'')+(GAME.done[x.id]?' done':''),x.ic);c.title=x.t;c.onclick=()=>{GAME.cur=x.id;saveGame();updateMissions();};sel.appendChild(c);});box.appendChild(sel);\n const card=el('div','mcard'+(done?' done':''),'<b>'+m.t+'<\/b><span>'+m.d+'<\/span>');const bar=el('div','mbar','<i style=\"width:'+Math.round(ok\/res.length*100)+'%\"><\/i>');card.appendChild(bar);\n const ul=el('div','mgoals');m.goals.forEach((gl,i)=>ul.appendChild(el('div','mg'+(res[i]?' ok':''),'<span>'+(res[i]?'\u2713':'\u25cb')+'<\/span>'+gl[0])));card.appendChild(ul);\n const foot=el('div','mfoot');if(done)foot.appendChild(el('span','mdone','\u0110\u00e3 ho\u00e0n th\u00e0nh \u00b7 +120 XP'));else{const h=el('button','gbtn','G\u1ee3i \u00fd');h.onclick=()=>toast(m.hint);foot.appendChild(h);foot.appendChild(el('span','mxp','Th\u01b0\u1edfng 120 XP'));}card.appendChild(foot);box.appendChild(card);}\nfunction openProfile(){const i=lvlOf(GAME.xp);const body=el('div');const nx=LEVELS[i+1];\n body.appendChild(el('div','prof','<img alt=\"PHOTO LAB \u2013 K-BLACK Studio\" decoding=\"async\" class=\"pav\" src=\"'+ph('mascot')+'\"><div class=\"plv\">'+(i+1)+'<\/div><div><b>'+LEVELS[i][1]+'<\/b><span>'+GAME.xp+' XP'+(nx?' \u00b7 c\u00f2n '+(nx[0]-GAME.xp)+' XP \u0111\u1ec3 l\u00ean '+nx[1]:' \u00b7 c\u1ea5p cao nh\u1ea5t')+'<\/span><\/div>'));\n body.appendChild(el('div','agrp','Nhi\u1ec7m v\u1ee5 studio'));const g=el('div','bgrid');MISSIONS.forEach(m=>{g.appendChild(el('div','badge'+(GAME.done[m.id]?' on':''),'<span>'+m.ic+'<\/span><b>'+m.t+'<\/b>'));});body.appendChild(g);\n body.appendChild(el('div','agrp','B\u00e0i h\u1ecdc'));body.appendChild(el('p','note',Object.keys(GAME.lessons).length+'\/'+LESSONS.length+' b\u00e0i \u0111\u00e3 ho\u00e0n th\u00e0nh \u00b7 \u0111i\u1ec3m ki\u1ec3m tra cao nh\u1ea5t '+GAME.quizBest+'\/10'));\n body.appendChild(el('div','agrp','C\u00e1c c\u1ea5p \u0111\u1ed9'));const lv=el('div','lvlist');LEVELS.forEach((l,k)=>lv.appendChild(el('div','lvi'+(k<=i?' on':''),'<span>'+(k+1)+'<\/span>'+l[1]+'<small>'+l[0]+' XP<\/small>')));body.appendChild(lv);\n const r=el('button','gbtn','Ch\u01a1i l\u1ea1i t\u1eeb \u0111\u1ea7u');r.style.marginTop='14px';r.onclick=()=>{if(!confirm('Xo\u00e1 to\u00e0n b\u1ed9 XP, nhi\u1ec7m v\u1ee5 v\u00e0 ti\u1ebfn \u0111\u1ed9?'))return;GAME={xp:0,done:{},lessons:{},cur:'m_meter',quizBest:0};saveGame();updPlayer();$('profModal').classList.remove('show');updateMissions();};body.appendChild(r);\n modal('profModal','H\u1ed3 s\u01a1 ng\u01b0\u1eddi ch\u01a1i',body);}\nfunction initGame(){if($('coachImg'))$('coachImg').src=ph('mascot');Object.keys(GAME.lessons).length||DONE.forEach(id=>{GAME.lessons[id]=1;});saveGame();updPlayer();$('player').onclick=openProfile;$('btnAssets').onclick=()=>openAssets('chars');}\n\/* ---------- setups with configurable example photos ---------- *\/\nfunction setupDiagram(k){const p=PRESET_DEF[k];if(!p)return '';const col={key:'#ffb259',fill:'#7aa2ff',rim:'#ff7a9c',kicker:'#ff7a9c',hair:'#c89bff',top:'#c89bff',bg:'#5ee0a0'};const cx=100,cy=92;let g='';\n const bdc=p.bd||'#8e9196';g+='<rect x=\"40\" y=\"16\" width=\"120\" height=\"7\" rx=\"3\" fill=\"'+bdc+'\" stroke=\"#5d6985\" stroke-width=\"1\"\/>';\n const many=p.subj==='group';if(many){for(let i=0;i<6;i++)g+='<circle cx=\"'+(70+i*12)+'\" cy=\"'+(cy+(i%2?6:-4))+'\" r=\"5\" fill=\"#d9b59c\"\/>';}else if(p.subj==='product'){g+='<rect x=\"93\" y=\"84\" width=\"14\" height=\"16\" rx=\"3\" fill=\"#7aa2ff\"\/>';}else{g+='<circle cx=\"'+cx+'\" cy=\"'+cy+'\" r=\"9\" fill=\"#d9b59c\"\/><path d=\"M'+cx+' '+(cy+9)+'l-4 6h8z\" fill=\"#d9b59c\"\/>';}\n g+='<path d=\"M100 172l-8 14h16z\" fill=\"#7aa2ff\"\/><path d=\"M100 172L72 104M100 172L128 104\" stroke=\"rgba(122,162,255,.25)\" stroke-width=\"1\"\/>';\n const placed=[];p.L.forEach(e=>{const o=Object.assign({},ROLES[e[0]].o,e[1]);const a=rad(o.az||0);const r=Math.min(o.dist||1.5,3.2)\/3.2*62+20;let x=cx+Math.sin(a)*r,y=cy+Math.cos(a)*r;let n=0;while(placed.some(q=>Math.hypot(q[0]-x,q[1]-y)<26)&&n<6){n++;x+=(n%2?1:-1)*n*16;}placed.push([x,y]);const ang=Math.atan2(cx-x,cy-y)*180\/Math.PI;const c=o.gel||col[e[0]]||'#ffb259';\n  g+='<line x1=\"'+x.toFixed(1)+'\" y1=\"'+y.toFixed(1)+'\" x2=\"'+cx+'\" y2=\"'+cy+'\" stroke=\"'+c+'\" stroke-opacity=\".35\" stroke-dasharray=\"3 3\"\/>';\n  g+='<g transform=\"translate('+x.toFixed(1)+' '+y.toFixed(1)+') rotate('+(-ang).toFixed(1)+')\"><rect x=\"-11\" y=\"-3\" width=\"22\" height=\"6\" rx=\"2\" fill=\"'+c+'\"\/><\/g>';\n  g+='<text x=\"'+x.toFixed(1)+'\" y=\"'+(y+(y<cy?-9:15)).toFixed(1)+'\" fill=\"#cfd8ea\" font-size=\"8.5\" font-weight=\"700\" text-anchor=\"middle\" font-family=\"Be Vietnam Pro,sans-serif\">'+(e[1].name||ROLE_NAME[e[0]])+'<\/text>';});\n return '<svg viewBox=\"0 0 200 200\" preserveAspectRatio=\"xMidYMid slice\" role=\"img\" aria-label=\"S\u01a1 \u0111\u1ed3 \u0111\u1eb7t \u0111\u00e8n nh\u00ecn t\u1eeb tr\u00ean\"><rect width=\"200\" height=\"200\" fill=\"#0d1322\"\/>'+g+'<\/svg>';}\nfunction initSetups(){const C=$('setupCards');Object.keys(SETUP_TXT).forEach(k=>{const u=slotURL('setup_'+k);const c=el('div','card sc');const m=el('div','scm'+(u?' ph':' dg'),u?'<img alt=\"PHOTO LAB \u2013 K-BLACK Studio\" decoding=\"async\" src=\"'+u+'\" alt=\"V\u00ed d\u1ee5 '+SETUP_TXT[k][0]+'\" loading=\"lazy\">':setupDiagram(k)+'<span class=\"tagd\">S\u01a1 \u0111\u1ed3 \u0111\u1eb7t \u0111\u00e8n<\/span>');\n const b=el('div','scb','<h3>'+SETUP_TXT[k][0]+'<\/h3><p>'+SETUP_TXT[k][1]+'<\/p>');const bt=el('button','pbtn sm','M\u1edf trong Studio 3D');bt.onclick=()=>openPreset(k);b.appendChild(bt);c.append(m,b);C.appendChild(c);});}\n\nfunction thumbKey(c){return 'kblack_thumb2_'+c.id+'_'+(((+c.rot||0)%360+360)%360);}\nfunction getThumb(c){if(c.thumb)return c.thumb;try{return localStorage.getItem(thumbKey(c))||'';}catch(e){return '';}}\nfunction makeThumb(c,ent){try{if(typeof THREE==='undefined'||!ent||ent.status!=='ok')return '';if(!THUMB_R){THUMB_R=new THREE.WebGLRenderer({antialias:true,preserveDrawingBuffer:true,alpha:true});THUMB_R.setSize(160,200,false);THUMB_R.outputEncoding=THREE.sRGBEncoding;THUMB_R.toneMapping=THREE.ACESFilmicToneMapping;THUMB_R.toneMappingExposure=1.05;}\n const sc=new THREE.Scene();sc.add(new THREE.HemisphereLight(0xffffff,0x2a3040,1.15));const dl=new THREE.DirectionalLight(0xffffff,1.7);dl.position.set(1.2,2.6,3);sc.add(dl);const rim=new THREE.DirectionalLight(0xffd9a8,.8);rim.position.set(-2,2.2,-2);sc.add(rim);\n const inst=charInstance(c,ent,false);sc.add(inst);const H=charH(c);const cam=new THREE.PerspectiveCamera(22,160\/200,.05,50);cam.position.set(0,H*.84,1.95);cam.lookAt(0,H*.8,0);\n THUMB_R.render(sc,cam);let url=THUMB_R.domElement.toDataURL('image\/webp',.82);if(!url||url.length<30)url=THUMB_R.domElement.toDataURL('image\/png');sc.remove(inst);if(url&&url.length>30){try{localStorage.setItem(thumbKey(c),url);}catch(e){}}return url;}catch(e){return '';}}\nfunction charListEl(){const w=el('div','clist');w.id='charList';\n ASSETS.characters.forEach(c=>{const e=CHAR_CACHE[c.url];const t=getThumb(c);const b=el('button','citem'+(ST.subj.char===c.id?' on':''),'<span class=\"ct\">'+(t?'<img alt=\"PHOTO LAB \u2013 K-BLACK Studio\" decoding=\"async\" src=\"'+t+'\">':charAvatar(c))+(e&&e.status==='loading'?'<i class=\"cload\">'+Math.round((e.prog||0)*100)+'%<\/i>':'')+(e&&e.status==='err'?'<i class=\"cerr\">L\u1ed7i t\u1ea3i<\/i>':'')+'<\/span><b>'+c.name+'<\/b>');b.title=c.name+(c.outfit?' \u2014 '+c.outfit:'');b.onclick=()=>selectChar(c.id);w.appendChild(b);});\n if(ST.subj.type==='group'&&ASSETS.characters.length>1){const b=el('button','citem'+(ST.subj.char==='all'?' on':''),'<span class=\"ct mix\">'+ASSETS.characters.slice(0,4).map(c=>{const t=getThumb(c);return t?'<img alt=\"PHOTO LAB \u2013 K-BLACK Studio\" decoding=\"async\" src=\"'+t+'\">':charAvatar(c);}).join('')+'<\/span><b>Xoay v\u00f2ng<\/b>');b.title='M\u1ed7i ng\u01b0\u1eddi trong nh\u00f3m m\u1ed9t nh\u00e2n v\u1eadt';b.onclick=()=>selectChar('all');w.appendChild(b);}\n const add=el('button','citem add','<span class=\"ct\">+<\/span><b>Th\u00eam<\/b>');add.onclick=()=>openAssets('chars');w.appendChild(add);return w;}\nfunction refreshCharList(){const o=$('charList');if(o)o.replaceWith(charListEl());}\nfunction selectChar(id){ST.subj.char=id;const ch=charById(id);if(ch)loadChar(ch,()=>{if(S3)S3.ss=null;DIRTY=true;updateMeter();refreshCharList();});buildLeft();changed();}\nfunction faceFixEl(ch){const fx=el('div','facefix','<span>Nh\u00e2n v\u1eadt quay sai h\u01b0\u1edbng? S\u1eeda m\u1ed9t l\u1ea7n, app nh\u1edb lu\u00f4n:<\/span>');[['\u21ba 90\u00b0',-90],['Quay 180\u00b0',180],['\u21bb 90\u00b0',90]].forEach(([l,d])=>{const b=el('button',null,l);b.onclick=()=>{ch.rot=(((+ch.rot||0)+d)%360+360)%360;saveAssets();if(S3)S3.ss=null;DIRTY=true;const e=CHAR_CACHE[ch.url];if(e&&e.status==='ok'&&!getThumb(ch))makeThumb(ch,e);buildLeft();toast('\u0110\u00e3 l\u01b0u h\u01b0\u1edbng m\u1eb7t cho '+ch.name);};fx.appendChild(b);});return fx;}\nfunction preloadChars(){if(navigator.connection&&navigator.connection.saveData)return;const q=ASSETS.characters.filter(c=>c.url&&!getThumb(c));let i=0,cur=null;const tick=setInterval(()=>{if(cur){const e=CHAR_CACHE[cur.url];if(e&&e.status==='loading')return;if(e&&e.status==='ok'&&!getThumb(cur)){makeThumb(cur,e);}refreshCharList();cur=null;}if(i>=q.length){clearInterval(tick);return;}cur=q[i++];if(!CHAR_CACHE[cur.url])loadChar(cur,null,true);},600);}\n\n\/* ---------- backdrop helpers ---------- *\/\nfunction lum(hex){const c=kToHex(hex);return .2126*c[0]+.7152*c[1]+.0722*c[2];}\nfunction kToHex(hex){hex=(hex||'#000').replace('#','');if(hex.length===3)hex=hex.split('').map(x=>x+x).join('');const f=i=>Math.pow(parseInt(hex.substr(i,2),16)\/255,2.2);return [f(0),f(2),f(4)];}\nconst GELS=[['','Kh\u00f4ng gel',1],['#ff3b3b','\u0110\u1ecf',.22],['#ff8a1f','Cam',.45],['#ffd23b','V\u00e0ng',.7],['#3bdc5a','Xanh l\u00e1',.3],['#2fd6e0','Cyan',.4],['#2f6bff','Xanh d\u01b0\u01a1ng',.18],['#8a3bff','T\u00edm',.15],['#ff4fb0','H\u1ed3ng',.35]];\nfunction gelOf(L){if(!L.gel)return {t:1,rgb:[1,1,1]};const g=GELS.find(x=>x[0]===L.gel);const c=kToHex(L.gel);const m=Math.max(c[0],c[1],c[2],1e-3);return {t:g?g[2]:clamp(lum(L.gel)*1.3,.12,.8),rgb:[c[0]\/m,c[1]\/m,c[2]\/m]};}\nfunction lightCol(L){const w=wbColor(L.kelvin,ST.cam.wb),g=gelOf(L).rgb;return [w[0]*g[0],w[1]*g[1],w[2]*g[2]];}\nfunction bdFloor(){const r=ST.room;return clamp(ST.bd.floor||2.2,0.3,Math.max(0.3,r.l-ST.bd.gap-0.6));}\nconst ASPECTS=[['2:3',2\/3],['4:5',.8],['1:1',1],['9:16',9\/16],['3:2',1.5],['16:9',16\/9]];\nfunction frameAR(){const a=ASPECTS.find(x=>x[0]===ST.cam.aspect);return a?a[1]:(ST.cam.portrait?2\/3:1.5);}\nfunction sensorWH(){const a=frameAR();if(a>=1){return a>=1.5?[36,36\/a]:[24*a,24];}return a<=2\/3?[36*a,36]:[24,24\/a];}\nfunction sensorV(){return sensorWH()[1];}function sensorH(){return sensorWH()[0];}\nfunction setAspect(k){ST.cam.aspect=k;ST.cam.portrait=frameAR()<1;syncOrientBtn();buildLeft();changed();}\nfunction bdW(){return Math.min(ST.bd.w||2.72,ST.room.w-0.3);}\nfunction bdMaxX(){return Math.max(0,ST.room.w\/2-bdW()\/2-0.05);}\nfunction clampBd(){ST.bd.x=clamp(ST.bd.x||0,-bdMaxX(),bdMaxX());}\nfunction moveBd(x,gap){const g=geo();const sz=g.sz;const l=ST.room.l;gap=clamp(gap,0.1,Math.max(0.1,sz+l\/2-0.3));ST.bd.gap=+gap.toFixed(3);ST.bd.x=+clamp(x,-bdMaxX(),bdMaxX()).toFixed(3);ST.subj.bd=+(sz-(-l\/2+ST.bd.gap)).toFixed(3);}\nfunction muslinDraw(x,w,h,base){x.fillStyle=base;x.fillRect(0,0,w,h);const r=seeded(29);for(let i=0;i<80;i++){const cx=r()*w,cy=r()*h,rad=40+r()*170;const light=r()>.5;const gr=x.createRadialGradient(cx,cy,0,cx,cy,rad);const a=.05+r()*.09;gr.addColorStop(0,light?'rgba(255,255,255,'+a.toFixed(3)+')':'rgba(0,0,0,'+a.toFixed(3)+')');gr.addColorStop(1,'rgba(0,0,0,0)');x.fillStyle=gr;x.fillRect(cx-rad,cy-rad,rad*2,rad*2);}\n const g=x.createRadialGradient(w\/2,h*.42,20,w\/2,h*.42,w*.72);g.addColorStop(0,'rgba(255,255,255,.14)');g.addColorStop(1,'rgba(0,0,0,.24)');x.fillStyle=g;x.fillRect(0,0,w,h);}\n\/* ---------- picture-in-picture viewfinder ---------- *\/\nfunction helperObjs(){const a=[S3.rotRing,S3.subjX,S3.camX,S3.dimBd,S3.dimCam,S3.camMark];Object.values(S3.lights).forEach(o=>{a.push(o.ring,o.dl,o.hl,o.stand&&o.stand.userData.x);});return a.filter(Boolean);}\nfunction renderPip(){const P=$('pip'),f=$('pipFrame');if(!P||!f||MODE==='pov'||P.classList.contains('min'))return;const R=S3.renderer;const cr=R.domElement.getBoundingClientRect(),fr=f.getBoundingClientRect();if(fr.width<10||cr.width<10)return;\n const x=fr.left-cr.left,y=cr.bottom-fr.bottom,w=fr.width,h=fr.height;const sv=sensorV();S3.pov.fov=2*Math.atan(sv\/(2*ST.cam.focal))*180\/Math.PI;S3.pov.aspect=w\/h;S3.pov.updateProjectionMatrix();\n const hide=helperObjs();hide.forEach(o=>{o._pv=o.visible;o.visible=false;});const sm=R.shadowMap;const au=sm.autoUpdate;sm.autoUpdate=false;\n R.setScissorTest(true);R.setViewport(x,y,w,h);R.setScissor(x,y,w,h);R.render(S3.scene,S3.pov);R.setScissorTest(false);const s=R.getSize(new THREE.Vector2());R.setViewport(0,0,s.x,s.y);sm.autoUpdate=au;hide.forEach(o=>{o.visible=o._pv;});}\nfunction placePanels(){const V=$('view3d'),pb=$('planBox'),P=$('pip'),po=$('pipOpen'),hud=$('hud');if(!V||!pb||!P)return;const vw=V.clientWidth||1000,vh=V.clientHeight||700;const ps=clamp(+ST.view.plan||250,160,Math.max(160,Math.min(560,vh-60)));\n pb.style.width=ps+'px';pb.style.height=(pb.classList.contains('min')?30:ps+30)+'px';\n const put=(el,pos,r,b)=>{if(!el)return;if(pos){const w=el.offsetWidth||0,h=el.offsetHeight||0;el.style.left=clamp(pos.x,0,Math.max(0,vw-w))+'px';el.style.top=clamp(pos.y,0,Math.max(0,vh-h))+'px';el.style.right='auto';el.style.bottom='auto';}else{el.style.left='auto';el.style.top='auto';el.style.right=r+'px';el.style.bottom=b+'px';}};\n put(pb,ST.view.planPos,12,12);const off=ST.view.planPos?12:ps+24;put(P,ST.view.pipPos,off,12);put(po,ST.view.pipPos,off,12);\n if(hud){hud.style.right='auto';const used=(ST.view.planPos&&ST.view.pipPos)?24:(off+(P.classList.contains('min')?150:(P.offsetWidth||220))+24);const avail=vw-used;hud.style.maxWidth=Math.max(0,avail)+'px';hud.style.display=(avail<300||MODE==='pov')?'none':'';}}\nfunction makeFloat(panel,handle,key){if(!panel||!handle)return;handle.addEventListener('pointerdown',e=>{if(e.target.closest('button,.grip,input'))return;e.preventDefault();const V=$('view3d').getBoundingClientRect();const R=panel.getBoundingClientRect();const ox=e.clientX-R.left,oy=e.clientY-R.top;handle.classList.add('dragging');\n  const mv=ev=>{ST.view[key]={x:Math.round(ev.clientX-V.left-ox),y:Math.round(ev.clientY-V.top-oy)};placePanels();};\n  const up=()=>{handle.classList.remove('dragging');window.removeEventListener('pointermove',mv);window.removeEventListener('pointerup',up);saveSoon();};window.addEventListener('pointermove',mv);window.addEventListener('pointerup',up);});\n handle.addEventListener('dblclick',e=>{if(e.target.closest('button'))return;delete ST.view[key];placePanels();saveSoon();toast('\u0110\u00e3 \u0111\u01b0a v\u1ec1 v\u1ecb tr\u00ed m\u1eb7c \u0111\u1ecbnh');});handle.title='K\u00e9o \u0111\u1ec3 di chuy\u1ec3n \u00b7 b\u1ea5m \u0111\u00fap \u0111\u1ec3 v\u1ec1 ch\u1ed7 c\u0169';}\nfunction initGrips(){makeFloat($('planBox'),$('planHead'),'planPos');makeFloat($('pip'),$('pip').querySelector('.piphead'),'pipPos');const pm=$('planMin');if(pm)pm.onclick=()=>{const pb=$('planBox');pb.classList.toggle('min');pm.textContent=pb.classList.contains('min')?'+':'\u2013';placePanels();};[['gripPlan','plan'],['gripPip','pip']].forEach(([id,k])=>{const g=$(id);if(!g)return;g.addEventListener('pointerdown',e=>{e.preventDefault();e.stopPropagation();const sx=e.clientX,sy=e.clientY;const f=$('pipFrame');const s0=k==='plan'?(+ST.view.plan||250):(f?f.getBoundingClientRect().width||200:200);const ar=frameAR();\n  const mv=ev=>{const dx=sx-ev.clientX,dy=sy-ev.clientY;if(k==='plan'){ST.view.plan=Math.round(clamp(s0+(ST.view.planPos?-Math.max(-dx,-dy):Math.max(dx,dy)),160,560));drawPlan($('plan'));}else{ST.view.pipW=Math.round(clamp(s0+Math.max(dx,dy*ar),150,900));}updPip();};\n  const up=()=>{window.removeEventListener('pointermove',mv);window.removeEventListener('pointerup',up);saveSoon();};window.addEventListener('pointermove',mv);window.addEventListener('pointerup',up);});});}\nfunction initPip(){initGrips();const P=$('pip');if(!P)return;P.querySelectorAll('[data-c]').forEach(b=>b.onclick=()=>{const c=ST.cam;const k=b.dataset.c;if(k==='hup')c.height=clamp(+(c.height+0.1).toFixed(2),0.4,2.5);if(k==='hdn')c.height=clamp(+(c.height-0.1).toFixed(2),0.4,2.5);if(k==='near')c.dist=clamp(+(c.dist-0.25).toFixed(2),0.5,12);if(k==='far')c.dist=clamp(+(c.dist+0.25).toFixed(2),0.5,12);if(k==='orient'){flipAspect();return;}if(k==='tu')c.tilt=clamp((c.tilt||0)+2,-35,35);if(k==='td')c.tilt=clamp((c.tilt||0)-2,-35,35);if(k==='pl')c.pan=clamp((c.pan||0)-2,-35,35);if(k==='pr')c.pan=clamp((c.pan||0)+2,-35,35);if(k==='aim0'){c.tilt=0;c.pan=0;}if(k==='orl')c.az=wrapAz((c.az||0)-10);if(k==='orr')c.az=wrapAz((c.az||0)+10);buildLeft();changed();});\n $('pipFrame').onclick=()=>setMode('pov');$('pipMin').onclick=()=>{P.classList.add('min');updPip();};$('pipOpen').onclick=()=>{P.classList.remove('min');updPip();};updPip();}\nconst PIPSZ=[['s','Nh\u1ecf',200],['m','V\u1eeba',300],['l','L\u1edbn',440]];\nfunction updPip(){const P=$('pip');if(!P)return;const c=ST.cam;const f=$('pipFrame');const V=$('view3d');const vh=(V&&V.clientHeight)||700,vw=(V&&V.clientWidth)||1000;const sz=(PIPSZ.find(x=>x[0]===(ST.view.pip||'m'))||PIPSZ[1])[2];\n const ps=clamp(+ST.view.plan||250,160,Math.max(160,Math.min(560,vh-60)));const off=ST.view.planPos?12:ps+24;const want=+ST.view.pipW||sz;\n const maxH=Math.max(150,vh-300),maxW=Math.max(160,vw-off-24-250);let w=Math.min(want,maxW);const ar=frameAR();let h=w\/ar;if(h>maxH){h=maxH;w=h*ar;}w=Math.round(w);h=Math.round(h);f.style.width=w+'px';f.style.height=h+'px';P.style.width=(w+14)+'px';\n placePanels();\n const zb=$('pipSz');if(zb){zb.innerHTML='';PIPSZ.forEach(x=>{const b=el('button',(!ST.view.pipW&&(ST.view.pip||'m')===x[0])?'on':'',x[1]);b.onclick=e=>{e.stopPropagation();ST.view.pip=x[0];ST.view.pipW=0;saveSoon();updPip();};zb.appendChild(b);});}\n const ab=$('pipAsp');if(ab){ab.innerHTML='';ASPECTS.forEach(a=>{const b=el('button',(c.aspect||'2:3')===a[0]?'on':'',a[0]);b.title='Khung '+a[0]+(a[1]<1?' (d\u1ecdc)':a[1]>1?' (ngang)':' (vu\u00f4ng)');b.onclick=()=>setAspect(a[0]);ab.appendChild(b);});}\n const fb=$('pipFoc');fb.innerHTML='';FOC.forEach(v=>{const b=el('button',v===c.focal?'on':'',String(v));b.title=v+'mm';b.onclick=()=>{c.focal=v;buildLeft();changed();};fb.appendChild(b);});\n const g=geo();const AIMq=camAim(g);const tilt=Math.asin(clamp(vnrm(vsub(AIMq,g.cam)).y,-1,1))*180\/Math.PI;$('pipH').textContent='cao '+c.height.toFixed(2)+' m';$('pipD').textContent='c\u00e1ch '+camDist(g).toFixed(2)+' m';if($('pipA'))$('pipA').textContent=(Math.abs(c.az||0)<1?'ch\u00ednh di\u1ec7n':azFmt(c.az).replace(' (tr\u01b0\u1edbc m\u1eb7t)','').replace(' (sau l\u01b0ng)',' (sau)'))+((c.tilt||c.pan)?' \u00b7 l\u1ec7ch '+(c.tilt?(c.tilt>0?'\u25b2':'\u25bc')+Math.abs(c.tilt)+'\u00b0':'')+(c.pan?(c.pan>0?'\u25b6':'\u25c0')+Math.abs(c.pan)+'\u00b0':''):'');$('pipOri').textContent='\u21c4 '+(frameAR()<1?'D\u1ecdc':frameAR()>1?'Ngang':'Vu\u00f4ng');\n $('pipInfo').textContent=c.focal+'mm \u00b7 '+(c.aspect||'2:3')+' \u00b7 '+(Math.abs(tilt)<2?'ngang t\u1ea7m m\u1eaft':tilt>0?'ng\u01b0\u1edbc l\u00ean '+Math.round(tilt)+'\u00b0':'ch\u00fac xu\u1ed1ng '+Math.round(-tilt)+'\u00b0');\n const hidden=MODE==='pov';P.style.display=hidden?'none':'';$('pipOpen').style.display=(!hidden&&P.classList.contains('min'))?'block':'none';}\n\n\/* ----- init ----- *\/\n(function(){const tb=document.querySelector('.top');if(tb&&tb.getBoundingClientRect().top+window.scrollY>4)document.documentElement.classList.add('kb-embed');})();\n$('logo').src=LOGO;initGame();$('mLesBtn').onclick=()=>{$('rail').classList.add('open');document.body.classList.add('noscroll');};$('railX').onclick=()=>{$('rail').classList.remove('open');document.body.classList.remove('noscroll');};$('mPrev').onclick=()=>{if(CURL>0)openLesson(CURL-1);};$('mNext').onclick=()=>{if(CURL<LESSONS.length-1)openLesson(CURL+1);};planEvents();initKeys();syncOrientBtn();openLesson(0);LASTSNAP=JSON.stringify(ST);updUndo();\n$('btnUndo').onclick=doUndo;$('btnRedo').onclick=doRedo;$('btnReset').onclick=()=>{setMode('orbit');resetView();};\ndocument.querySelectorAll('.vbar [data-v]').forEach(b=>b.onclick=()=>toggleView(b.dataset.v));\n$('btnKeys').onclick=()=>$('keyModal').classList.add('show');$('keyClose').onclick=()=>$('keyModal').classList.remove('show');$('keyModal').onclick=e=>{if(e.target===$('keyModal'))$('keyModal').classList.remove('show');};\n<\/script>\n<!--PLM-->\n<style>\n@media (max-width:760px){\nhtml.plm{--plmT:calc(54px + env(safe-area-inset-top));--plmN:calc(64px + env(safe-area-inset-bottom));margin-top:0!important;background:#070b16}\nhtml.plm #wpadminbar{display:none!important}\nhtml.plm body{background:#070b16;-webkit-tap-highlight-color:transparent}\nhtml.plm.plm-st,html.plm.plm-st body{overflow:hidden!important;height:100%!important;overscroll-behavior:none}\nhtml.plm .top{position:fixed!important;left:0;right:0;top:0;height:var(--plmT)!important;padding:env(safe-area-inset-top) 14px 0!important;flex-wrap:nowrap!important;gap:10px!important;z-index:60;background:rgba(7,11,22,.78)!important;backdrop-filter:saturate(1.5) blur(16px);-webkit-backdrop-filter:saturate(1.5) blur(16px);border-bottom:1px solid rgba(255,255,255,.06)!important}\nhtml.plm .top .tabs,html.plm #btnAssets,html.plm #btnKeys{display:none!important}\nhtml.plm .brand img{height:16px!important}\nhtml.plm .brand span{display:inline-block!important;font:800 10px 'Be Vietnam Pro',sans-serif;letter-spacing:.22em;color:#7aa2ff;border-left:1px solid rgba(255,255,255,.14);padding-left:9px;text-transform:uppercase}\nhtml.plm .player{margin-left:auto!important;padding:3px 10px 3px 3px!important;border-radius:12px}\nhtml.plm .player .pinfo{display:flex!important;min-width:0!important;width:74px}\nhtml.plm .player .pinfo b{font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\nhtml.plm .player .pinfo small{display:none}\nhtml.plm .tacts{display:none!important}\nhtml.plm .plm-acts{display:flex!important;flex-direction:row;gap:0;position:static;order:-1;margin:0!important;width:auto!important;flex:0 0 auto}\nhtml.plm .plm-acts .tbtn{width:34px;height:30px;min-width:0;padding:0!important;border-radius:8px;display:flex;align-items:center;justify-content:center;background:none;border:0;color:#cfd8ea}\nhtml.plm .plm-acts svg{width:17px;height:17px}\n\/* bottom nav *\/\n.plm-nav{display:none}\nhtml.plm .plm-nav{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:80;height:var(--plmN);padding-bottom:env(safe-area-inset-bottom);background:rgba(7,11,22,.86);backdrop-filter:saturate(1.5) blur(18px);-webkit-backdrop-filter:saturate(1.5) blur(18px);border-top:1px solid rgba(255,255,255,.07)}\nhtml.plm .plm-nav button{flex:1;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;background:none;border:0;color:#6f7c99;font:700 10.5px 'Be Vietnam Pro',sans-serif;letter-spacing:.02em;transition:color .2s}\nhtml.plm .plm-nav svg{width:23px;height:23px;transition:transform .25s cubic-bezier(.2,.8,.2,1),filter .25s}\nhtml.plm .plm-nav button.on{color:#fff}\nhtml.plm .plm-nav button.on svg{color:#7aa2ff;transform:translateY(-1px) scale(1.08);filter:drop-shadow(0 0 10px rgba(47,107,255,.75))}\nhtml.plm .plm-nav button.on:before{content:\"\";position:absolute;top:-1px;left:30%;right:30%;height:2px;border-radius:2px;background:linear-gradient(90deg,transparent,#2f6bff,transparent)}\nhtml.plm .plm-nav button:active svg{transform:scale(.9)}\n\/* learn *\/\nhtml.plm #pLearn.pane.on{display:block!important;height:auto!important;padding:var(--plmT) 0 calc(var(--plmN) + 8px)}\nhtml.plm .mlesbar{top:var(--plmT)!important;padding:10px 12px!important;background:rgba(7,11,22,.88)!important;border-bottom:1px solid rgba(255,255,255,.06)!important;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}\nhtml.plm .mlesbar button{min-height:42px;border-radius:12px!important;background:#121a2c!important;border-color:#22304f!important}\nhtml.plm #mPrev,html.plm #mNext{width:46px!important}\nhtml.plm .rail.open{z-index:95!important;padding-top:calc(14px + env(safe-area-inset-top))!important;padding-bottom:calc(30px + env(safe-area-inset-bottom))!important}\nhtml.plm .lbody{padding:18px 16px 26px!important}\nhtml.plm .lwrap h1{font-size:27px!important;line-height:1.18!important;letter-spacing:-.6px;margin-bottom:12px}\nhtml.plm .lwrap .lead{font-size:15.5px!important;line-height:1.65}\nhtml.plm .lwrap p,html.plm .lwrap li{font-size:15px;line-height:1.7}\nhtml.plm .lwrap h2{font-size:18.5px!important;margin:30px 0 12px!important;letter-spacing:-.2px}\nhtml.plm .crumb{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:#7aa2ff;font-weight:700}\nhtml.plm .sim{padding:12px!important;border-radius:18px!important;background:linear-gradient(180deg,#121a2e,#0d1324)!important;border-color:#1f2b48!important}\nhtml.plm .sim canvas,html.plm .fig img{border-radius:12px!important}\nhtml.plm .tip{border-radius:0 14px 14px 0;font-size:14px}\nhtml.plm .qz{border-radius:16px;padding:14px}\nhtml.plm .qz button.opt{padding:13px 14px!important;font-size:14.5px!important;border-radius:12px!important;margin-bottom:8px!important}\nhtml.plm .pbtn,html.plm .gbtn{min-height:48px;border-radius:14px!important;font-size:14px!important}\nhtml.plm .pbtn{background:linear-gradient(135deg,#2f6bff,#1e3fa0)!important;box-shadow:0 10px 24px -12px rgba(47,107,255,.9)}\nhtml.plm .card{border-radius:16px}\nhtml.plm .chki{padding:13px 14px;border-radius:12px}\nhtml.plm .ctlh{font-size:12.5px}\nhtml.plm input[type=range]{-webkit-appearance:none;appearance:none;height:30px;background:transparent}\nhtml.plm input[type=range]::-webkit-slider-runnable-track{height:6px;border-radius:6px;background:linear-gradient(90deg,#1e3fa0,#2f6bff 50%,#26324f 50%);background:#26324f}\nhtml.plm input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:24px;height:24px;margin-top:-9px;border-radius:50%;background:#fff;border:0;box-shadow:0 0 0 4px rgba(47,107,255,.45),0 4px 10px rgba(0,0,0,.5)}\nhtml.plm input[type=range]::-moz-range-track{height:6px;border-radius:6px;background:#26324f}\nhtml.plm input[type=range]::-moz-range-thumb{width:24px;height:24px;border-radius:50%;background:#fff;border:0;box-shadow:0 0 0 4px rgba(47,107,255,.45)}\nhtml.plm select,html.plm input[type=text]{min-height:44px;font-size:15px!important;border-radius:12px!important}\nhtml.plm .seg button{padding:9px 12px!important;font-size:12.5px!important;border-radius:10px!important}\nhtml.plm .msg{bottom:calc(var(--plmN) + 14px)!important;max-width:calc(100% - 28px);border-radius:14px}\nhtml.plm .modal{padding:calc(20px + env(safe-area-inset-top)) 12px calc(var(--plmN) + 12px)!important;z-index:96!important}\nhtml.plm .mbox{border-radius:18px!important}\n\/* studio *\/\nhtml.plm #pStudio.pane.on{display:block!important;position:fixed!important;left:0;right:0;top:var(--plmT);bottom:calc(var(--plmN) + var(--plm-sb,150px) - 20px);height:auto!important;flex-direction:initial!important;transition:bottom .32s cubic-bezier(.2,.8,.2,1)}\nhtml.plm.plm-dragging #pStudio.pane.on{transition:none}\nhtml.plm #pStudio .view{position:absolute!important;inset:0!important;height:auto!important;order:0!important}\nhtml.plm #view3d canvas{touch-action:none}\nhtml.plm .vbar{left:0!important;right:0!important;top:8px!important;padding:0 10px;justify-content:flex-start!important;flex-wrap:nowrap!important;overflow-x:auto;scrollbar-width:none;pointer-events:auto!important;gap:6px!important}\nhtml.plm .vbar::-webkit-scrollbar{display:none}\nhtml.plm .vgrp{flex:0 0 auto;border-radius:12px!important;background:rgba(10,15,28,.82)!important;border-color:rgba(122,162,255,.16)!important}\nhtml.plm .vgrp button{padding:8px 11px!important;font-size:12px!important;white-space:nowrap;border-radius:9px!important}\nhtml.plm .meter{top:52px!important;left:10px!important;width:auto!important;max-width:calc(100% - 20px);padding:4px 5px 4px 12px!important;border-radius:99px!important;background:rgba(10,15,28,.82)!important;border-color:rgba(122,162,255,.18)!important;box-shadow:none!important;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);display:flex;align-items:center;gap:8px;cursor:pointer}\nhtml.plm .meter:not(.plm-open) .mt,html.plm .meter:not(.plm-open) .rows,html.plm .meter:not(.plm-open) .warn,html.plm .meter:not(.plm-open) button,html.plm .meter:not(.plm-open) .sub{display:none!important}\nhtml.plm .meter:not(.plm-open) .big{font-size:18px!important;margin:0!important;line-height:1}\nhtml.plm .meter:not(.plm-open) .ev{margin:0!important;padding:4px 9px!important;border-radius:99px!important;font-size:10.5px!important;white-space:nowrap;max-width:170px;overflow:hidden;text-overflow:ellipsis}\nhtml.plm .meter.plm-open{display:block;left:10px!important;right:10px!important;max-width:none!important;border-radius:16px!important;padding:12px 14px!important;z-index:9;background:rgba(12,18,32,.96)!important}\nhtml.plm .meter.plm-open .big{font-size:34px!important}\nhtml.plm .meter .mt{font-size:10.5px}\nhtml.plm .hud{display:none!important}\nhtml.plm .labels .lb{font-size:10.5px}\nhtml.plm .pip{right:10px!important;bottom:10px!important}\nhtml.plm .pipopen{left:10px!important;bottom:10px!important;top:auto!important;padding:6px 11px!important;font-size:11.5px!important;border-radius:99px!important;background:rgba(10,15,28,.82)!important;border:1px solid rgba(122,162,255,.18)!important}\nhtml.plm .plm-sheet .planbox{position:relative!important;inset:auto!important;left:auto!important;right:auto!important;top:auto!important;bottom:auto!important;width:100%!important;height:min(86vw,360px)!important;border-radius:16px!important;margin:4px 0 10px}\nhtml.plm .plm-sheet .planhead .grip,html.plm .plm-sheet #planMin{display:none}\n.plm-sheet{display:none}\nhtml.plm .plm-sheet{display:flex;flex-direction:column;position:fixed;left:0;right:0;bottom:var(--plmN);z-index:65;height:var(--plm-sh,150px);background:linear-gradient(180deg,rgba(18,26,46,.97),rgba(11,16,30,.98));backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);border-radius:22px 22px 0 0;border-top:1px solid rgba(122,162,255,.22);box-shadow:0 -20px 40px -14px rgba(0,0,0,.75);transition:height .32s cubic-bezier(.2,.8,.2,1)}\nhtml.plm.plm-dragging .plm-sheet{transition:none}\nhtml.plm:not(.plm-st) .plm-sheet{display:none}\n.plm-grab{flex:0 0 auto;height:24px;display:flex;align-items:center;justify-content:center;touch-action:none;cursor:grab}\n.plm-grab i{width:42px;height:5px;border-radius:3px;background:rgba(255,255,255,.22)}\n.plm-tabs{flex:0 0 auto;display:flex;gap:6px;overflow-x:auto;padding:0 12px 10px;scrollbar-width:none;touch-action:pan-x}\n.plm-tabs::-webkit-scrollbar{display:none}\n.plm-tabs button{flex:0 0 auto;display:flex;align-items:center;gap:6px;padding:9px 13px;border-radius:99px;background:#151f36;border:1px solid #243150;color:#9aa6c2;font:700 12.5px 'Be Vietnam Pro',sans-serif;white-space:nowrap;transition:all .2s}\n.plm-tabs button.on{background:linear-gradient(135deg,#2f6bff,#1e3fa0);border-color:#3b74ff;color:#fff;box-shadow:0 6px 16px -8px rgba(47,107,255,.9)}\n.plm-body{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding:4px 14px 24px;border-top:1px solid rgba(255,255,255,.05)}\nhtml.plm .plm-body .sp{display:block!important;position:static!important;width:100%!important;min-width:0!important;max-width:none!important;border:0!important;background:none!important;padding:8px 0 0!important;overflow:visible!important;height:auto!important}\nhtml.plm .plm-body .grp>h4{font-size:14px}\nhtml.plm .plm-body .presets{grid-template-columns:1fr 1fr}\nhtml.plm .plm-body .presets button{padding:11px 10px;border-radius:12px;font-size:12.5px}\nhtml.plm .plm-body .lrow{padding:11px 12px;border-radius:12px}\nhtml.plm .plm-body .nudge button{padding:9px 0;font-size:15px}\n.plm-sheet:not([data-t=den]) #spRight,.plm-sheet[data-t=den] #spLeft,.plm-sheet[data-t=mat] #spLeft,.plm-sheet:not([data-t=mat]) #planBox{display:none!important}\n.plm-sheet[data-t=mau] #spLeft>*:not(:nth-child(1)),.plm-sheet[data-t=phong] #spLeft>*:not(:nth-child(2)):not(:nth-child(3)),.plm-sheet[data-t=chu] #spLeft>*:not(:nth-child(4)),.plm-sheet[data-t=may] #spLeft>*:not(:nth-child(5)){display:none!important}\n.plm-tip{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);z-index:8;background:rgba(10,15,28,.9);border:1px solid rgba(122,162,255,.25);color:#cfd8ea;font:600 12px 'Be Vietnam Pro',sans-serif;padding:9px 14px;border-radius:99px;white-space:nowrap;pointer-events:none;animation:plmTip 5.5s ease forwards}\n@keyframes plmTip{0%{opacity:0;transform:translate(-50%,8px)}8%,85%{opacity:1;transform:translate(-50%,0)}100%{opacity:0}}\nhtml.plm .pane.on{animation:plmIn .35s cubic-bezier(.2,.8,.2,1)}\n@keyframes plmIn{from{opacity:0}to{opacity:1}}\n}\n<\/style>\n<script>\n(function(){\nvar mq=window.matchMedia('(max-width:760px)'),H=document.documentElement,g=function(i){return document.getElementById(i)};\nif(!g('pStudio')||!g('pLearn'))return;\nvar SV='<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">';\nvar IC={learn:SV+'<path d=\"M2 8.5l10-5 10 5-10 5z\"\/><path d=\"M6 11v5c0 1.6 2.7 3 6 3s6-1.4 6-3v-5\"\/><path d=\"M22 8.5v6\"\/><\/svg>',\nstudio:SV+'<rect x=\"3\" y=\"4\" width=\"10\" height=\"8\" rx=\"1.5\"\/><path d=\"M13 6.5l5-2.5v8l-5-2.5\"\/><path d=\"M8 12v8M5 20h6\"\/><circle cx=\"18.5\" cy=\"18\" r=\"2.5\"\/><\/svg>',\nme:SV+'<circle cx=\"12\" cy=\"8\" r=\"4\"\/><path d=\"M4 21c1.5-4 4.5-6 8-6s6.5 2 8 6\"\/><\/svg>',\nundo:SV+'<path d=\"M9 14L4 9l5-5\"\/><path d=\"M4 9h10a6 6 0 010 12h-3\"\/><\/svg>',redo:SV+'<path d=\"M15 14l5-5-5-5\"\/><path d=\"M20 9H10a6 6 0 000 12h3\"\/><\/svg>',\nsave:SV+'<path d=\"M6 3h12v18l-6-4-6 4z\"\/><\/svg>',list:SV+'<path d=\"M3 6.5h6l2 2h10V19H3z\"\/><\/svg>'};\nvar TABS=[['den','\u0110\u00e8n'],['mau','Setup m\u1eabu'],['chu','Ch\u1ee7 th\u1ec3'],['may','M\u00e1y \u1ea3nh'],['phong','Ph\u00f2ng & ph\u00f4ng'],['mat','M\u1eb7t b\u1eb1ng']];\nvar moved=[],built=false,nav,sh,acts,snap='peek';\nfunction mv(el,to){if(!el)return;moved.push([el,el.parentNode,el.nextSibling]);to.appendChild(el)}\nfunction sizes(){var vh=window.innerHeight,top=g('pStudio').getBoundingClientRect?0:0;var nav=64,t=54;return{peek:116,half:Math.round(vh*.46),full:Math.max(300,vh-t-nav-8)}}\nfunction setSnap(s,noAnim){snap=s;var z=sizes(),h=z[s];H.style.setProperty('--plm-sh',h+'px');H.style.setProperty('--plm-sb',Math.min(h,z.half)+'px')}\nfunction sync(){var st=g('pStudio').classList.contains('on');H.classList.toggle('plm-st',st&&H.classList.contains('plm'));\n if(nav)[].forEach.call(nav.children,function(b){b.classList.toggle('on',b.dataset.go===(st?'studio':'learn'))});\n if(st&&!sync.tip&&H.classList.contains('plm')){sync.tip=1;var pp=g('pip');if(pp&&!pp.classList.contains('min')&&g('pipMin'))setTimeout(function(){g('pipMin').click()},300);var v=document.querySelector('#pStudio .view');if(v){var t=document.createElement('div');t.className='plm-tip';t.textContent='1 ng\u00f3n: xoay \u00b7 2 ng\u00f3n: zoom \u00b7 ch\u1ea1m \u0111\u00e8n \u0111\u1ec3 ch\u1ecdn';v.appendChild(t);setTimeout(function(){t.remove()},6000)}}}\nfunction build(){if(built)return;built=true;\n var vp=document.querySelector('meta[name=viewport]');if(vp&&vp.content.indexOf('viewport-fit')<0)vp.content+=', viewport-fit=cover';\n if(!document.querySelector('meta[name=theme-color]')){var m=document.createElement('meta');m.name='theme-color';m.content='#070b16';document.head.appendChild(m)}\n nav=document.createElement('nav');nav.className='plm-nav';\n nav.innerHTML='<button data-go=\"learn\">'+IC.learn+'<span>H\u1ecdc nhi\u1ebfp \u1ea3nh<\/span><\/button><button data-go=\"studio\">'+IC.studio+'<span>Studio 3D<\/span><\/button><button data-go=\"me\">'+IC.me+'<span>H\u1ed3 s\u01a1<\/span><\/button>';\n document.body.appendChild(nav);\n nav.addEventListener('click',function(e){var b=e.target.closest('button');if(!b)return;try{navigator.vibrate&&navigator.vibrate(8)}catch(x){}\n  if(b.dataset.go==='me'){g('player').click();return}var t=document.querySelector('.tab[data-t=\"'+b.dataset.go+'\"]');if(t)t.click();window.scrollTo(0,0);sync()});\n sh=document.createElement('div');sh.className='plm-sheet';sh.dataset.t='den';\n sh.innerHTML='<div class=\"plm-grab\" aria-label=\"K\u00e9o \u0111\u1ec3 m\u1edf r\u1ed9ng\"><i><\/i><\/div><div class=\"plm-tabs\">'+TABS.map(function(x,i){return '<button data-k=\"'+x[0]+'\"'+(i?'':' class=\"on\"')+'>'+x[1]+'<\/button>'}).join('')+'<\/div><div class=\"plm-body\"><\/div>';\n g('pStudio').appendChild(sh);var body=sh.querySelector('.plm-body');\n mv(g('spRight'),body);mv(g('spLeft'),body);mv(g('planBox'),body);\n acts=g('studioActs');if(acts){var vb=document.querySelector('#pStudio .vbar');mv(acts,vb);if(vb)vb.insertBefore(acts,vb.firstChild);acts.classList.add('plm-acts','vgrp');\n  var ic={btnUndo:'undo',btnRedo:'redo',btnSaveSet:'save',btnMySet:'list'};Object.keys(ic).forEach(function(id){var b=g(id);if(b){b.dataset.plmTxt=b.innerHTML;b.innerHTML=IC[ic[id]];b.setAttribute('aria-label',b.title||b.dataset.plmTxt)}})}\n sh.querySelector('.plm-tabs').addEventListener('click',function(e){var b=e.target.closest('button');if(!b)return;sh.dataset.t=b.dataset.k;[].forEach.call(this.children,function(x){x.classList.toggle('on',x===b)});body.scrollTop=0;try{b.scrollIntoView({inline:'center',block:'nearest',behavior:'smooth'})}catch(x){}if(snap==='peek')setSnap('half');if(b.dataset.k==='mat')setTimeout(function(){window.dispatchEvent(new Event('resize'))},350)});\n var gr=sh.querySelector('.plm-grab'),y0=0,h0=0,dragging=false,t0=0;\n gr.addEventListener('pointerdown',function(e){dragging=true;y0=e.clientY;t0=Date.now();h0=sh.getBoundingClientRect().height;H.classList.add('plm-dragging');try{gr.setPointerCapture(e.pointerId)}catch(x){}});\n gr.addEventListener('pointermove',function(e){if(!dragging)return;var z=sizes(),h=Math.max(z.peek-30,Math.min(z.full,h0-(e.clientY-y0)));H.style.setProperty('--plm-sh',h+'px')});\n function end(e){if(!dragging)return;dragging=false;H.classList.remove('plm-dragging');var dy=e.clientY-y0,dt=Date.now()-t0,z=sizes(),h=h0-dy;\n  if(Math.abs(dy)<6){setSnap(snap==='peek'?'half':'peek');return}\n  var v=dy\/Math.max(1,dt);if(v<-.5)setSnap(h>z.half?'full':'half');else if(v>.5)setSnap(h<z.half?'peek':'half');\n  else{var best='peek',bd=1e9;['peek','half','full'].forEach(function(k){var d=Math.abs(z[k]-h);if(d<bd){bd=d;best=k}});setSnap(best)}}\n gr.addEventListener('pointerup',end);gr.addEventListener('pointercancel',end);\n var mt=g('meter');if(mt)mt.addEventListener('click',function(e){if(e.target.closest('button'))return;mt.classList.toggle('plm-open')});\n setSnap('peek');\n new MutationObserver(sync).observe(g('pStudio'),{attributes:true,attributeFilter:['class']});\n window.addEventListener('resize',function(){if(H.classList.contains('plm'))setSnap(snap)});\n}\nfunction unbuild(){if(!built)return;built=false;for(var i=moved.length-1;i>=0;i--){var m=moved[i];m[1].insertBefore(m[0],m[2]&&m[2].parentNode===m[1]?m[2]:null)}moved=[];\n if(acts){acts.classList.remove('plm-acts','vgrp');['btnUndo','btnRedo','btnSaveSet','btnMySet'].forEach(function(id){var b=g(id);if(b&&b.dataset.plmTxt)b.innerHTML=b.dataset.plmTxt})}\n if(nav)nav.remove();if(sh)sh.remove();nav=sh=null}\nfunction apply(){if(mq.matches){H.classList.add('plm');build()}else{H.classList.remove('plm','plm-st');unbuild()}sync()}\napply();if(mq.addEventListener)mq.addEventListener('change',apply);else mq.addListener(apply);\n})();\n<\/script>\n<!--\/PLM-->\n<\/body>\n<\/html>\n<!--KBPLT--><style>\n@media (min-width:761px) and (max-width:1199px){\n.top .brand{flex:none}\n.rail{width:236px!important;flex:none}\n.lbody{padding:26px 26px 60px!important}\n.lwrap{max-width:none!important}\n.sim.side{display:block!important}\n.sim.side>canvas:not(.histc){display:block;width:100%!important;max-width:440px;height:auto!important;max-height:none!important;min-height:0!important;margin:0 auto 14px!important;grid-row:auto!important}\n.sim.side .histc{width:100%!important;max-width:440px;margin:6px auto 0!important;display:block}\n.simrow,.simrow.two{grid-template-columns:1fr 1fr!important;gap:6px 18px!important}\n.simrow>.gbtn,.simrow>button{grid-column:1\/-1}\n.read{display:grid!important;grid-template-columns:repeat(4,1fr);gap:8px!important;align-items:end}\n.tbl{display:block;overflow-x:auto}\n}\n@media (min-width:761px) and (max-width:899px){.top .brand span{display:none!important}.top .tabs .tab{padding-left:12px!important;padding-right:12px!important}}\n.coach .kkcoach{position:relative;flex:none;width:74px;height:94px;border-radius:14px;overflow:hidden;background:radial-gradient(80% 70% at 50% 35%,rgba(79,139,255,.45),rgba(10,16,40,.2) 70%),#0b1226;border:1px solid rgba(122,215,255,.25);align-self:center}\n.coach .kkin{position:absolute;width:170%;aspect-ratio:470\/600;left:-35%;top:10%}.coach .kkin canvas,.coach .kkin img{position:absolute!important;left:0;top:0;width:100%!important;height:100%!important;display:block;max-width:none!important}\n.coach .kkcoach:after{content:\"\";position:absolute;right:6px;bottom:6px;width:9px;height:9px;border-radius:50%;background:#2fe38a;box-shadow:0 0 0 2px #0b1226}\n<\/style>\n<script>\/* KIKI puppet v1 \u2014 WebGL 2.5D: breathing, head sway\/tilt\/nod, blink, lip-sync, emotions. (c) K-BLACK *\/\n(function(){\nif(window.KikiPuppet)return;\nvar VS='attribute vec2 p;varying vec2 v;void main(){v=vec2(p.x*.5+.5,.5-p.y*.5);gl_Position=vec4(p,0.,1.);}';\nvar FS=[\n'precision highp float;varying vec2 v;uniform sampler2D T;uniform vec2 S;',\n'uniform float uBreath,uRot,uNod,uSway,uBlink,uMouth,uSmile,uJump,uBrow,uLean,uShrug,uArmL,uArmR;uniform vec2 uGaze;',\n'uniform vec2 sL,sR,hip;uniform vec4 bA;uniform vec2 bB;',\n'uniform vec2 eL,eR,mo,piv;uniform float chin,eRx,eRy,mRx;',\n'mat2 rot(float a){float c=cos(a),s=sin(a);return mat2(c,-s,s,c);}',\n'float ell(vec2 p,vec2 c,vec2 r){vec2 d=(p-c)\/r;return dot(d,d);}',\n'vec4 tex(vec2 p){vec2 u=p\/S;if(u.x<0.||u.y<0.||u.x>1.||u.y>1.)return vec4(0.);return texture2D(T,u);}',\n'void main(){',\n' vec2 p=v*S;',\n' p.y+=uJump; p.x-=uSway;',\n\/* whole-body lean around hips *\/\n' float lw=1.-smoothstep(hip.y-170.,hip.y+10.,p.y);',\n' p=hip+rot(-uLean*lw)*(p-hip);',\n\/* shrug: shoulders+head lift *\/\n' float sh=1.-smoothstep(sL.y+40.,sL.y+130.,p.y);',\n' float k1=smoothstep(sL.y+55.,sL.y+115.,p.y),k2=smoothstep(sL.y+215.,sL.y+265.,p.y);',\n' float bLx=mix(mix(bA.x,bA.y,k1),bB.x,k2), bRx=mix(mix(bA.z,bA.w,k1),bB.y,k2);',\n' float aL=(1.-smoothstep(bLx-7.,bLx+7.,p.x))*smoothstep(sL.y-15.,sL.y+55.,p.y);',\n' float aR=smoothstep(bRx-7.,bRx+7.,p.x)*smoothstep(sR.y-15.,sR.y+55.,p.y);',\n' p.y+=uShrug*7.*max(sh,max(aL,aR)*(1.-.75*smoothstep(sL.y+60.,sL.y+330.,p.y)));',\n\/* arms swing around shoulders *\/\n' p=sL+rot(uArmL*aL)*(p-sL);',\n' p=sR+rot(-uArmR*aR)*(p-sR);',\n\/* breathing: torso scales from bottom *\/\n' float tor=smoothstep(piv.y-10.,piv.y+40.,p.y);',\n' vec2 bc=vec2(piv.x,S.y);',\n' p=bc+(p-bc)\/vec2(1.+uBreath*.010*tor,1.+uBreath*.014*tor);',\n\/* head: rotate + nod around neck pivot, weight fades through neck *\/\n' float hw=1.-smoothstep(piv.y-26.,piv.y+14.,p.y);',\n' vec2 q=p-piv; q=rot(-uRot*hw)*q; q.y-=uNod*hw; p=piv+q;',\n\/* mouth (lip-sync): lower lip + jaw move down, gap filled with mouth interior *\/\n' float fx=clamp(1.-pow(abs(p.x-mo.x)\/mRx,2.),0.,1.);',\n' float jaw=1.-smoothstep(chin-6.,chin+16.,p.y);',\n' float open=uMouth*4.2*fx;',\n' vec4 col; bool inner=false;',\n' if(p.y>mo.y && abs(p.x-mo.x)<mRx*1.6){',\n'   float d=open*jaw*(p.y<mo.y+open?1.:1.);',\n'   if(p.y<mo.y+open*.92 && fx>.05){inner=true;}',\n'   p.y-=open*jaw;',\n' }',\n\/* smile: lift mouth corners *\/\n' float cor=smoothstep(mRx*.3,mRx*1.2,abs(p.x-mo.x))*(1.-smoothstep(mRx*1.2,mRx*1.9,abs(p.x-mo.x)));',\n' float near=1.-smoothstep(3.,10.,abs(p.y-mo.y));',\n' p.y+=uSmile*1.6*cor*near;',\n\/* brow raise: lift region above eyes *\/\n' float bw=exp(-ell(p,(eL+eR)*.5-vec2(0.,10.),vec2(34.,9.)));',\n' p.y+=uBrow*2.2*bw;',\n' for(int i=0;i<2;i++){vec2 e=i==0?eL:eR;float g=1.-smoothstep(.35,.95,length((p-e)\/vec2(eRx,eRy)));p-=uGaze*g;}',\n' col=tex(p);',\n\/* blink: upper lid slides down over each eye *\/\n' for(int i=0;i<2;i++){',\n'   vec2 e=i==0?eL:eR;',\n'   vec2 d=(p-e)\/vec2(eRx,eRy);',\n'   float inE=1.-smoothstep(.75,1.15,length(d));',\n'   if(inE>0.){',\n'     float lidY=e.y-eRy+uBlink*1.45*eRy+uBlink*1.3*(1.-d.x*d.x);',\n'     float cover=smoothstep(lidY+.6,lidY-.6,p.y)*inE;',\n'     vec4 skin=tex(vec2(p.x,e.y-eRy-1.6));',\n'     vec4 lid=mix(skin,skin*vec4(.82,.76,.74,1.),smoothstep(lidY-2.5,lidY,p.y));',\n'     col=mix(col,lid,cover*step(.02,uBlink));',\n'     float lash=(1.-smoothstep(.2,1.3,abs(p.y-lidY)))*(1.-smoothstep(.85,1.25,length(d)))*smoothstep(.15,.5,uBlink);',\n'     col.rgb=mix(col.rgb,vec3(.1,.06,.06),lash*.72);',\n'   }',\n' }',\n' if(inner){ float t=clamp((p.y-mo.y)\/max(open,.001),0.,1.);',\n'   vec3 m=mix(vec3(.88,.84,.80),vec3(.30,.08,.09),smoothstep(.05,.35,t)); col=vec4(mix(col.rgb,m,.92*fx),col.a);}',\n' gl_FragColor=col;',\n'}'].join('\\n');\n\nfunction KikiPuppet(host,src,L){\n  var cv=document.createElement('canvas');cv.className='kiki-cv';cv.setAttribute('aria-hidden','true');\n  var gl=cv.getContext('webgl',{premultipliedAlpha:false,alpha:true,antialias:true});\n  var api={ok:false,canvas:cv,talk:function(){},mood:function(){},react:function(){},level:function(){},destroy:function(){}};\n  if(!gl)return api;\n  function sh(t,s){var o=gl.createShader(t);gl.shaderSource(o,s);gl.compileShader(o);if(!gl.getShaderParameter(o,gl.COMPILE_STATUS)){console.warn(gl.getShaderInfoLog(o));return null}return o}\n  var pr=gl.createProgram(),vs=sh(gl.VERTEX_SHADER,VS),fs=sh(gl.FRAGMENT_SHADER,FS);if(!vs||!fs)return api;\n  gl.attachShader(pr,vs);gl.attachShader(pr,fs);gl.linkProgram(pr);gl.useProgram(pr);\n  var b=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,b);gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),gl.STATIC_DRAW);\n  var loc=gl.getAttribLocation(pr,'p');gl.enableVertexAttribArray(loc);gl.vertexAttribPointer(loc,2,gl.FLOAT,false,0,0);\n  var U={};['T','S','uBreath','uRot','uNod','uSway','uBlink','uMouth','uSmile','uJump','uBrow','uLean','uShrug','uArmL','uArmR','uGaze','sL','sR','hip','bA','bB','eL','eR','mo','piv','chin','eRx','eRy','mRx'].forEach(function(n){U[n]=gl.getUniformLocation(pr,n)});\n  var img=new Image();img.crossOrigin='anonymous';\n  var st={t0:performance.now(),blink:0,nextBlink:1.5,blinkT:-1,mouth:0,mTarget:0,talking:false,mood:'idle',moodT:0,react:'',reactT:-9,lvl:0,smile:.35,rotBias:0,nodBias:0,brow:0,squint:0,lean:0,shrug:0,arm:0,gx:0,gy:0,gtx:0,gty:0,nextGaze:1,gest:-9,gestA:0,gestS:1,cur:{lean:0,shrug:0,armL:0,armR:0}},raf=0,visible=true;\n  img.onload=function(){\n    var tx=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,tx);gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,false);\n    gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,img);\n    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);\n    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);\n    gl.uniform2f(U.S,L.w||470,L.h||600);gl.uniform2f(U.eL,L.eL[0],L.eL[1]);gl.uniform2f(U.eR,L.eR[0],L.eR[1]);gl.uniform2f(U.mo,L.mo[0],L.mo[1]);gl.uniform2f(U.piv,L.piv[0],L.piv[1]);\n    gl.uniform1f(U.chin,L.chin);var D=KikiPuppet.L;gl.uniform2f(U.sL,(L.sL||D.sL)[0],(L.sL||D.sL)[1]);gl.uniform2f(U.sR,(L.sR||D.sR)[0],(L.sR||D.sR)[1]);gl.uniform2f(U.hip,(L.hip||D.hip)[0],(L.hip||D.hip)[1]);var bA=L.bA||D.bA;gl.uniform4f(U.bA,bA[0],bA[1],bA[2],bA[3]);var bB=L.bB||D.bB;gl.uniform2f(U.bB,bB[0],bB[1]);gl.uniform1f(U.eRx,L.eRx);gl.uniform1f(U.eRy,L.eRy);gl.uniform1f(U.mRx,L.mRx);\n    gl.enable(gl.BLEND);gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);\n    cv.style.aspectRatio=img.width+'\/'+img.height;\n    api.ok=true;host.appendChild(cv);host.classList.add('kiki-live');resize();loop();\n  };\n  img.onerror=function(){};\n  img.src=src;\n  function resize(){var r=cv.getBoundingClientRect(),d=Math.min(2.5,Math.max(1.5,(window.devicePixelRatio||1)*1.25));var w=Math.max(2,Math.round(r.width*d)),h=Math.max(2,Math.round(r.height*d));if(cv.width!==w||cv.height!==h){cv.width=w;cv.height=h}gl.viewport(0,0,cv.width,cv.height)}\n  var ro=window.ResizeObserver?new ResizeObserver(resize):null;if(ro)ro.observe(cv);else addEventListener('resize',resize);\n  var io=window.IntersectionObserver?new IntersectionObserver(function(e){visible=e[0].isIntersecting;if(visible&&!raf)loop()}):null;if(io)io.observe(cv);\n  function ease(a,b,k){return a+(b-a)*k}\n  var prev=performance.now();\n  function loop(){\n    raf=0;if(visible&&!document.hidden)raf=requestAnimationFrame(loop);\n    var now=performance.now(),t=(now-st.t0)\/1000,dt=Math.min(.05,(now-prev)\/1000);prev=now;\n    \/\/ blink scheduler\n    if(st.blinkT<0&&t>st.nextBlink){st.blinkT=0;st.nextBlink=t+2.2+Math.random()*3.6+(Math.random()<.18?-1.9:0)}\n    var bl=0;if(st.blinkT>=0){st.blinkT+=dt;var bt=st.blinkT\/.16;bl=bt<.5?bt*2:Math.max(0,2-bt*2);if(st.blinkT>.16)st.blinkT=-1}\n    \/\/ talking mouth\n    if(st.sp){var se=(now-st.sp.t0)\/1000,sy=st.sp.syl,k=Math.floor(se\/st.sp.per);if(k>=sy.length){st.sp=null;st.talking=false;st.mTarget=st.lvl}else{var ph=(se-k*st.sp.per)\/st.sp.per;st.mTarget=ph<.68?sy[k]*(ph<.12?ph\/.12:1):0.04}}\n    else if(st.talking){if(Math.random()<dt*9)st.mTarget=Math.random()<.25?0.05:(.3+Math.random()*.6)}else st.mTarget=st.lvl;\n    st.mouth=ease(st.mouth,st.mTarget,Math.min(1,dt*(st.mTarget>st.mouth?26:18)));\n    \/\/ reactions\n    var rt=t-st.reactT,rot=0,nod=0,jump=0,sway=0,mouthAdd=0,brow=st.brow,smile=st.smile,sq=st.squint;\n    if(st.react==='laugh'&&rt<1.6){var a=1-rt\/1.6;nod+=Math.sin(rt*26)*2.4*a;rot+=Math.sin(rt*13)*.015*a;mouthAdd=.75*a;sq=Math.max(sq,.55*a);smile=1}\n    if(st.react==='jump'&&rt<.8){jump=-Math.sin(Math.min(1,rt\/.8)*Math.PI)*16;smile=1;brow=Math.max(brow,.6)}\n    if(st.react==='shock'&&rt<2){var s=Math.min(1,rt*6)*(rt>1.6?(2-rt)\/.4:1);mouthAdd=.95*s;brow=Math.max(brow,s);nod-=2*s}\n    if(st.react==='nod'&&rt<1){nod+=Math.sin(rt*Math.PI*3)*2.2*(1-rt)}\n    if(st.react==='shake'&&rt<1.1){rot+=Math.sin(rt*Math.PI*5)*.05*(1-rt\/1.1)}\n    if(st.react==='glitch'&&rt<.9){sway+=(Math.random()-.5)*10*(1-rt\/.9)}\n    \/\/ idle life\n    var breath=Math.sin(t*1.7)*.5+.5;\n    rot+=Math.sin(t*.55)*.022+Math.sin(t*1.31)*.008+st.rotBias;\n    nod+=Math.sin(t*.8+1)*.9+Math.sin(t*.29+2)*.6+st.nodBias+(st.talking||st.sp?Math.sin(t*5.1)*.45+st.mouth*.6:0);\n    sway+=Math.sin(t*.45)*1.4;\n    \/\/ ---- body language ----\n    var B={lean:st.lean,shrug:st.shrug,armL:st.arm,armR:st.arm};\n    B.lean+=Math.sin(t*.37)*.006+Math.sin(t*.91+1)*.003;\n    B.armL+=Math.sin(t*.8)*.006+breath*.004;B.armR+=Math.sin(t*.8+.6)*.006+breath*.004;\n    var spk=st.talking||st.sp;\n    if(spk&&t-st.gest>2.2+Math.random()*2.5&&Math.random()<dt*1.4){st.gest=t;st.gestS=Math.random()<.5?1:-1;st.gestA=.014+Math.random()*.016}\n    var gt=t-st.gest;if(gt<1.3){var gk=Math.sin(Math.min(1,gt\/1.3)*Math.PI);if(st.gestS>0)B.armR-=st.gestA*1.6*gk;else B.armL-=st.gestA*1.6*gk;B.lean+=st.gestS*.012*gk;B.shrug+=.15*gk}\n    if(st.react==='laugh'&&rt<1.6){var la=1-rt\/1.6;B.lean-=.02*la;B.armL-=.02*la*(.6+.4*Math.sin(rt*20));B.armR-=.02*la*(.6+.4*Math.sin(rt*20+1));B.shrug+=.5*la*(.5+.5*Math.sin(rt*24))}\n    if(st.react==='shock'&&rt<2){var sk=Math.min(1,rt*6)*(rt>1.6?(2-rt)\/.4:1);B.shrug+=.8*sk;B.armL-=.03*sk;B.armR-=.03*sk;B.lean-=.012*sk}\n    if(st.react==='jump'&&rt<.8){var jk=Math.sin(Math.min(1,rt\/.8)*Math.PI);B.armL-=.025*jk;B.armR-=.025*jk;B.shrug+=.5*jk}\n    if(st.react==='shake'&&rt<1.1){B.lean+=Math.sin(rt*Math.PI*5)*.01*(1-rt\/1.1)}\n    if(st.react==='nod'&&rt<1){B.shrug+=Math.sin(rt*Math.PI*3)*.2*(1-rt)}\n    B.armL=Math.max(-.045,Math.min(.006,B.armL));B.armR=Math.max(-.045,Math.min(.006,B.armR));\n    var C=st.cur,ke=Math.min(1,dt*7);C.lean=ease(C.lean,B.lean,ke);C.shrug=ease(C.shrug,B.shrug,ke);C.armL=ease(C.armL,B.armL,ke*1.3);C.armR=ease(C.armR,B.armR,ke*1.3);\n    \/\/ ---- gaze (saccades) ----\n    if(t>st.nextGaze){st.nextGaze=t+1.2+Math.random()*3;var r0=Math.random();if(r0<.55){st.gtx=0;st.gty=0}else{st.gtx=(Math.random()-.5)*2.4;st.gty=(Math.random()-.5)*1.2}if(st.gazeBias){st.gtx=st.gazeBias[0];st.gty=st.gazeBias[1]}}\n    st.gx=ease(st.gx,st.gtx,Math.min(1,dt*28));st.gy=ease(st.gy,st.gty,Math.min(1,dt*28));\n    if(api.force){var F=api.force;if(F.blink!=null)bl=F.blink,sq=0;if(F.mouth!=null)st.mouth=F.mouth,mouthAdd=0;if(F.rot!=null)rot=F.rot;if(F.nod!=null)nod=F.nod;if(F.smile!=null)smile=F.smile;if(F.brow!=null)brow=F.brow;if(F.breath!=null)breath=F.breath;if(F.sway!=null)sway=F.sway}\n    gl.clearColor(0,0,0,0);gl.clear(gl.COLOR_BUFFER_BIT);\n    gl.uniform1f(U.uBreath,breath);gl.uniform1f(U.uRot,rot);gl.uniform1f(U.uNod,nod);gl.uniform1f(U.uSway,sway);\n    gl.uniform1f(U.uBlink,Math.max(bl,sq));gl.uniform1f(U.uMouth,0*Math.min(1,st.mouth+mouthAdd));gl.uniform1f(U.uSmile,smile);gl.uniform1f(U.uJump,jump);gl.uniform1f(U.uBrow,brow);gl.uniform1f(U.uLean,C.lean);gl.uniform1f(U.uShrug,C.shrug);gl.uniform1f(U.uArmL,C.armL);gl.uniform1f(U.uArmR,C.armR);gl.uniform2f(U.uGaze,st.gx,st.gy);\n    gl.drawArrays(gl.TRIANGLE_STRIP,0,4);\n  }\n  document.addEventListener('visibilitychange',function(){if(!document.hidden&&!raf)loop()});\n  var MOODS={idle:{r:0,n:0,s:.35,b:0,q:0},smug:{r:.06,n:-.5,s:.9,b:.2,q:.28,l:.012,a:-.008,g:[1.6,0]},wink:{r:-.05,n:0,s:.8,b:.3,q:.15,l:-.01},think:{r:.09,n:-1.2,s:.1,b:.55,q:.1,l:.015,sh:.25,g:[-1.4,-.9]},shock:{r:0,n:-2,s:0,b:1,q:0,sh:.6,a:-.015,l:-.01},laugh:{r:.03,n:0,s:1,b:.3,q:.4,l:-.012,a:-.01},evil:{r:-.07,n:1,s:.75,b:0,q:.35,l:.02,g:[-1.2,.3]},sweat:{r:.05,n:.5,s:.3,b:.7,q:.05,sh:.5,a:-.012},love:{r:-.04,n:0,s:1,b:.4,q:.2,l:-.018,sh:.2},cool:{r:.02,n:-.8,s:.6,b:0,q:.22,l:-.012,a:-.004}};\n  api.talk=function(on){st.talking=!!on;if(!on)st.sp=null};\n  function vow(w){w=w.toLowerCase();if(\/[a\u00e0\u00e1\u1ea3\u00e3\u1ea1\u0103\u1eb1\u1eaf\u1eb3\u1eb5\u1eb7\u00e2\u1ea7\u1ea5\u1ea9\u1eab\u1ead]\/.test(w))return .95;if(\/[o\u00f2\u00f3\u1ecf\u00f5\u1ecd\u00f4\u1ed3\u1ed1\u1ed5\u1ed7\u1ed9\u01a1\u1edd\u1edb\u1edf\u1ee1\u1ee3]\/.test(w))return .72;if(\/[u\u00f9\u00fa\u1ee7\u0169\u1ee5\u01b0\u1eeb\u1ee9\u1eed\u1eef\u1ef1]\/.test(w))return .5;if(\/[e\u00e8\u00e9\u1ebb\u1ebd\u1eb9\u00ea\u1ec1\u1ebf\u1ec3\u1ec5\u1ec7]\/.test(w))return .6;if(\/[i\u00ec\u00ed\u1ec9\u0129\u1ecby\u1ef3\u00fd\u1ef7\u1ef9\u1ef5]\/.test(w))return .42;return .3}\n  api.speak=function(text,secs){var ws=String(text).replace(\/<[^>]+>\/g,'').split(\/\\s+\/).filter(function(w){return \/[\\w\u00c0-\u1ef9]\/.test(w)});if(!ws.length)return;var per=Math.max(.13,Math.min(.24,(secs||ws.length*.18)\/ws.length));st.sp={t0:performance.now(),per:per,syl:ws.map(function(w){return vow(w)*(.8+Math.random()*.25)})};st.talking=true;return per*ws.length};\n  api.level=function(v){st.lvl=v||0};\n  api.mood=function(m){var o=MOODS[m]||MOODS.idle;st.rotBias=o.r;st.nodBias=o.n;st.smile=o.s;st.brow=o.b;st.squint=o.q;st.lean=o.l||0;st.shrug=o.sh||0;st.arm=o.a||0;st.gazeBias=o.g||null;st.nextGaze=0;clearTimeout(st.mt);if(m&&m!=='idle')st.mt=setTimeout(function(){api.mood('idle')},4200)};\n  api.react=function(r){st.react=r;st.reactT=(performance.now()-st.t0)\/1000;if(r==='laugh'||r==='jump'||r==='shock')st.blinkT=-1};\n  api.blink=function(){st.blinkT=0};\n  api.destroy=function(){cancelAnimationFrame(raf);if(ro)ro.disconnect();if(io)io.disconnect();cv.remove()};\n  return api;\n}\nKikiPuppet.L={eL:[214.5,86.8],eR:[252.5,89.6],mo:[230.6,125.6],piv:[231,176],chin:149,eRx:10.5,eRy:4.6,mRx:16.5,sL:[152,212],sR:[320,212],hip:[235,610],bA:[150,134,322,334],bB:[114,350]};\nwindow.KikiPuppet=KikiPuppet;\n})();\n<\/script>\n<script>\n(function(){\nvar SRC='https:\/\/kblack.vn\/wp-content\/uploads\/2026\/10\/kblack-kiki-ai-host-hd.webp',tries=0;\nfunction go(){\n  var img=document.getElementById('coachImg');\n  if(!img||!window.KikiPuppet){if(++tries<60)return setTimeout(go,250);return}\n  if(img.dataset.kk)return;img.dataset.kk=1;\n  var box=document.createElement('div');box.className='kkcoach';box.setAttribute('role','img');box.setAttribute('aria-label','KIKI \u2013 tr\u1ee3 l\u00fd \u1ea3o K-BLACK');\n  var inn=document.createElement('div');inn.className='kkin';box.appendChild(inn);var fb=document.createElement('img');fb.src=SRC;fb.alt='';inn.appendChild(fb);\n  img.style.display='none';img.parentNode.insertBefore(box,img);\n  var P=null;try{P=KikiPuppet(inn,SRC,KikiPuppet.L)}catch(e){}\n  var b=img.parentNode.querySelector('div>b');if(b&&\/Tr\u1ee3 l\u00fd\/.test(b.textContent))b.textContent='KIKI \u00b7 Tr\u1ee3 l\u00fd K-BLACK';\n  if(!P)return;\n  var mo=new MutationObserver(function(){if(inn.classList.contains('kiki-live'))fb.remove()});mo.observe(inn,{attributes:true});\n  function chat(ms,mood,r){P.talk(true);if(mood)P.mood(mood);if(r)P.react(r);setTimeout(function(){P.talk(false)},ms||1400)}\n  document.addEventListener('click',function(e){\n    var t=e.target.closest&&e.target.closest('button.les,.lnav .pbtn,#mPrev,#mNext');if(t)chat(1300,'smug','nod');\n    var g=e.target.closest&&e.target.closest('.sim .gbtn');if(g)chat(900,'think');\n  },true);\n  setTimeout(function(){chat(1600,'wink','nod')},1200);\n}\nif(document.readyState==='loading')document.addEventListener('DOMContentLoaded',go);else go();\n})();\n<\/script><!--\/KBPLT-->\n\n<!--KBK back--><style>.kbk{display:inline-flex;align-items:center;justify-content:center;flex:0 0 var(--kbs,36px);box-sizing:border-box;width:var(--kbs,36px)!important;min-width:var(--kbs,36px);max-width:var(--kbs,36px);height:var(--kbs,36px)!important;padding:0!important;margin:0;border-radius:calc(var(--kbs,36px)*.34);background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);color:#fff!important;text-decoration:none!important;cursor:pointer;transition:background .2s,transform .15s;-webkit-tap-highlight-color:transparent}.kbk:hover{background:rgba(255,255,255,.15)}.kbk:active{transform:scale(.92)}.kbk svg{width:calc(var(--kbs,36px)*.46)!important;height:calc(var(--kbs,36px)*.46)!important;max-width:none;flex:none;display:block}.kbk.lt{background:rgba(0,0,0,.05);border-color:rgba(0,0,0,.12);color:#111!important}.kbk.fx{position:absolute;left:max(14px,env(safe-area-inset-left));z-index:2147483000}.kbk-w{display:inline-flex!important;align-items:center;gap:10px;vertical-align:middle;max-width:100%;flex-wrap:nowrap}<\/style>\n<script>(function(){var SEL='.brand',FB='\/uu-dai\/',n=0;\nfunction lum(e){while(e&&e.nodeType===1){var c=getComputedStyle(e).backgroundColor,m=c.match(\/[\\d.]+\/g);if(m&&(m.length<4||+m[3]>.5))return(.2126*m[0]+.7152*m[1]+.0722*m[2])\/255;e=e.parentElement}return 0}\nfunction fixedHost(e){while(e&&e!==document.body){if(getComputedStyle(e).position==='fixed')return e;e=e.parentElement}return null}\nfunction mk(){var a=document.createElement('a');a.className='kbk';a.href=FB;a.setAttribute('aria-label','Quay l\u1ea1i');a.innerHTML='<svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M15 5l-7 7 7 7\"\/><\/svg>';a.onclick=function(e){var r=document.referrer;if(r&&r.indexOf(location.host)>-1&&history.length>1){e.preventDefault();history.back()}};return a}\nfunction later(f){f();[120,400,1000,2500].forEach(function(t){setTimeout(f,t)});addEventListener('load',f);addEventListener('resize',f);try{new ResizeObserver(f).observe(document.body)}catch(e){}}\nfunction go(){if(document.querySelector('.kbk'))return;var t=SEL&&document.querySelector(SEL);if(SEL&&!t&&n++<40){setTimeout(go,150);return}\nvar b=mk();if(t){var vis=t;t=t.closest('a')||t;var r=t.getBoundingClientRect();b.style.setProperty('--kbs',Math.max(32,Math.min(40,Math.round(r.height+12)))+'px');if(lum(t)>.55)b.classList.add('lt');\nif(r.left<70){var w=document.createElement('span');w.className='kbk-w';t.parentNode.insertBefore(w,t);w.appendChild(b);w.appendChild(t);\nlater(function(){b.style.top='0px';b.style.position='relative';w.style.marginLeft='';var q=vis.getBoundingClientRect(),p=b.getBoundingClientRect();if(q.height>4)b.style.top=Math.round((q.top+q.height\/2)-(p.top+p.height\/2))+'px';if(p.left<12)w.style.marginLeft=Math.round(12-p.left)+'px'});return}\nvar host=fixedHost(t);b.classList.add('fx');(host||document.body).appendChild(b);\nlater(function(){var q=vis.getBoundingClientRect(),h=host?host.getBoundingClientRect():{top:-scrollY,left:-scrollX};if(q.height<4)q=t.getBoundingClientRect();b.style.top=Math.round(q.top-h.top+q.height\/2-b.offsetHeight\/2)+'px';b.style.left=Math.max(14,Math.round(q.left-h.left-b.offsetWidth-12))+'px'});return}\nif(lum(document.body)>.55)b.classList.add('lt');b.classList.add('fx');b.style.top='calc(max(14px,env(safe-area-inset-top)) + var(--wp-admin--admin-bar--height,0px))';document.body.appendChild(b)}\nvar mo=0;function watch(){if(mo)return;mo=new MutationObserver(function(){if(!document.querySelector('.kbk')){clearTimeout(watch.t);watch.t=setTimeout(function(){n=0;go()},120)}});mo.observe(document.body,{childList:true,subtree:true})}\nfunction start(){go();watch()}\nif(document.readyState==='loading')document.addEventListener('DOMContentLoaded',start);else start()})();<\/script>\n\n<script>\/*KBPAT v1 \u2013 nh\u1eadn di\u1ec7n ki\u1ec3u s\u00e1ng*\/(function(){if(window.__kbPat2)return;window.__kbPat2=1;var open=false;\nfunction lab(){try{if(typeof ST==='undefined'||typeof keyL!=='function'||typeof geo!=='function')return;var m=document.getElementById('meter');if(!m||!m.offsetParent)return;\nvar b=document.getElementById('kbPat');if(!b){b=document.createElement('button');b.type='button';b.id='kbPat';b.setAttribute('aria-label','Ki\u1ec3u s\u00e1ng hi\u1ec7n t\u1ea1i');b.onclick=function(){open=!open;b.__h='';lab()};m.parentNode.insertBefore(b,m.nextSibling);}\nif(b.parentNode!==m.parentNode)m.parentNode.insertBefore(b,m.nextSibling);\nvar mz=getComputedStyle(m);b.style.cssText='position:absolute;z-index:'+((+mz.zIndex||5)+1)+';left:'+m.offsetLeft+'px;top:'+(m.offsetTop+m.offsetHeight+6)+'px;max-width:'+Math.min(Math.max(m.offsetWidth,200),280)+'px;text-align:left;padding:6px 10px;border-radius:10px;background:rgba(8,10,18,.82);border:1px solid rgba(159,184,255,.28);font:500 11.5px\/1.38 Montserrat,system-ui,sans-serif;color:#e8ecf6;cursor:pointer;backdrop-filter:blur(6px)';\nif(ST.subj&&ST.subj.type==='product'){b.style.display='none';return}\nvar k=keyL(),txt,tip;\nif(!k){txt='Ch\u01b0a c\u00f3 \u0111\u00e8n ch\u00ednh';tip='Th\u00eam \u0111\u00e8n vai tr\u00f2 Key \u0111\u1ec3 b\u1eaft \u0111\u1ea7u.'}else{var a=Math.abs(wrapAz(k.az)),G=geo(),dh=k.height-G.faceY;\nvar fillLow=ST.lights.some(function(L){return L.on&&L.role==='fill'&&L.height<G.faceY-0.05&&Math.abs(wrapAz(L.az))<25});\nif(a>110){txt='Ng\u01b0\u1ee3c s\u00e1ng \/ vi\u1ec1n';tip='\u0110\u00e8n ch\u00ednh \u1edf sau l\u01b0ng: m\u1eb7t t\u1ed1i, vi\u1ec1n s\u00e1ng. Mu\u1ed1n s\u00e1ng m\u1eb7t th\u00ec \u0111\u01b0a key ra tr\u01b0\u1edbc.'}\nelse if(a>60){txt='Split \u2013 chia \u0111\u00f4i m\u1eb7t';tip='N\u1eeda m\u1eb7t s\u00e1ng, n\u1eeda m\u1eb7t t\u1ed1i: k\u1ecbch t\u00ednh, m\u1ea1nh m\u1ebd.'}\nelse if(a>35){var ok=dh>=0.3&&dh<=0.9;txt=ok?'Rembrandt':'G\u1ea7n Rembrandt';tip=ok?'Tam gi\u00e1c s\u00e1ng d\u01b0\u1edbi m\u1eaft ph\u00eda t\u1ed1i \u2013 kinh \u0111i\u1ec3n, c\u00f3 chi\u1ec1u s\u00e2u.':'\u0110\u1eb7t key cao h\u01a1n m\u1eb7t 0,3\u20130,9 m \u0111\u1ec3 ra tam gi\u00e1c s\u00e1ng.'}\nelse if(a>12){txt='Loop';tip='B\u00f3ng m\u0169i nh\u1ecf ch\u1ebfch xu\u1ed1ng m\u00e1 \u2013 t\u1ef1 nhi\u00ean, h\u1ee3p \u1ea3nh profile.'}\nelse if(dh>=0.25){txt=fillLow?'Clamshell (beauty)':'Butterfly';tip=fillLow?'Key tr\u00ean cao + b\u00f9 ph\u00eda d\u01b0\u1edbi: da m\u1ecbn, h\u1ee3p beauty.':'B\u00f3ng h\u00ecnh c\u00e1nh b\u01b0\u1edbm d\u01b0\u1edbi m\u0169i \u2013 sang, h\u1ee3p beauty, th\u1eddi trang.'}\nelse{txt='S\u00e1ng ph\u1eb3ng';tip='\u00cdt b\u00f3ng, m\u1eb7t thi\u1ebfu kh\u1ed1i. N\u00e2ng key cao h\u01a1n m\u1eb7t ho\u1eb7c l\u1ec7ch sang b\u00ean.'}}\nvar r='';try{var x=ratioKF(meter());r=isFinite(x)&&x>0?'Key:Fill '+(x>=10?Math.round(x):x.toFixed(1))+':1':(k?'ch\u01b0a c\u00f3 fill':'')}catch(e){}\nvar h='<b style=\"color:#9fb8ff\">'+txt+'<\/b>'+(r?' <span style=\"opacity:.8\">\u00b7 '+r+'<\/span>':'')+(open?'<br><span style=\"opacity:.75\">'+tip+'<\/span>':' <span style=\"opacity:.55\">\u24d8<\/span>');b.style.display='';if(b.__h!==h){b.innerHTML=h;b.__h=h}}catch(e){}}\nsetInterval(lab,600);})();\n<\/script>\n<script>(function(){if(window.__kbDay)return;window.__kbDay=1;\n\/* K-BLACK Photo Lab \u00b7 TH\u1eec TH\u00c1CH M\u1ed6I NG\u00c0Y (30\/10\/2026)\n   M\u1ed7i ng\u00e0y 1 b\u00e0i setup \u00e1nh s\u00e1ng (ch\u1ecdn theo ng\u00e0y, gi\u1edd VN). Ch\u1ea5m t\u1ef1 \u0111\u1ed9ng theo ki\u1ec3u s\u00e1ng + t\u1ec9 l\u1ec7 Key:Fill (c\u00f9ng c\u00e1ch t\u00ednh v\u1edbi nh\u00e3n ki\u1ec3u s\u00e1ng #kbPat).\n   Gi\u1eef \u0111\u00fang 2 gi\u00e2y l\u00e0 ho\u00e0n th\u00e0nh \u2192 chu\u1ed7i ng\u00e0y (localStorage) \u2192 t\u1ea1o th\u1ebb k\u1ebft qu\u1ea3 1080\u00d71350 \u0111\u1ec3 chia s\u1ebb. *\/\nvar C=[\n {id:'loop',p:'loop',r:[2,4],t:'Loop cho \u1ea3nh profile',g:'Ra ki\u1ec3u s\u00e1ng Loop, Key:Fill t\u1eeb 2:1 \u0111\u1ebfn 4:1.',h:'\u0110\u1eb7t key l\u1ec7ch 15\u201335\u00b0 so v\u1edbi m\u1eb7t, cao h\u01a1n m\u1eb7t m\u1ed9t ch\u00fat; th\u00eam fill ph\u00eda \u0111\u1ed1i di\u1ec7n, y\u1ebfu h\u01a1n key.'},\n {id:'rem',p:'rembrandt',r:[3,6],t:'Rembrandt kinh \u0111i\u1ec3n',g:'Ra ki\u1ec3u Rembrandt (tam gi\u00e1c s\u00e1ng d\u01b0\u1edbi m\u1eaft), Key:Fill 3:1 \u2013 6:1.',h:'Key l\u1ec7ch 35\u201360\u00b0, cao h\u01a1n m\u1eb7t 0,3\u20130,9 m. Fill y\u1ebfu \u0111\u1ec3 gi\u1eef kh\u1ed1i.'},\n {id:'bfly',p:'butterfly',r:[2,4],t:'Butterfly th\u1eddi trang',g:'Ra ki\u1ec3u Butterfly (b\u00f3ng c\u00e1nh b\u01b0\u1edbm d\u01b0\u1edbi m\u0169i), Key:Fill 2:1 \u2013 4:1.',h:'Key ngay tr\u01b0\u1edbc m\u1eb7t, cao h\u01a1n m\u1eb7t \u2265 0,25 m. Fill th\u1ea5p v\u00e0 nh\u1eb9.'},\n {id:'clam',p:'clamshell',r:[1.5,3],t:'Clamshell beauty',g:'Ra ki\u1ec3u Clamshell: key tr\u00ean cao + fill ph\u00eda d\u01b0\u1edbi, Key:Fill 1,5:1 \u2013 3:1.',h:'Key tr\u01b0\u1edbc m\u1eb7t tr\u00ean cao; fill \u0111\u1eb7t th\u1ea5p h\u01a1n m\u1eb7t, g\u1ea7n tr\u1ee5c \u1ed1ng k\u00ednh.'},\n {id:'split',p:'split',r:[6,99],t:'Split k\u1ecbch t\u00ednh',g:'Ra ki\u1ec3u Split (chia \u0111\u00f4i m\u1eb7t), Key:Fill t\u1eeb 6:1 tr\u1edf l\u00ean ho\u1eb7c kh\u00f4ng fill.',h:'Key l\u1ec7ch 60\u2013110\u00b0 sang m\u1ed9t b\u00ean. T\u1eaft ho\u1eb7c gi\u1ea3m fill th\u1eadt nhi\u1ec1u.'},\n {id:'rim',p:'rim',r:[0,99],t:'Ng\u01b0\u1ee3c s\u00e1ng \/ vi\u1ec1n t\u00f3c',g:'Ra ki\u1ec3u ng\u01b0\u1ee3c s\u00e1ng: \u0111\u00e8n ch\u00ednh ph\u00eda sau, t\u1ea1o vi\u1ec1n s\u00e1ng quanh ng\u01b0\u1eddi.',h:'\u0110\u01b0a key ra sau l\u01b0ng m\u1eabu (l\u1ec7ch h\u01a1n 110\u00b0). C\u00f3 th\u1ec3 th\u00eam fill nh\u1eb9 ph\u00eda tr\u01b0\u1edbc.'},\n {id:'softl',p:'loop',r:[1.3,2.5],t:'Loop s\u00e1ng m\u1ec1m (high-key)',g:'Ra ki\u1ec3u Loop v\u1edbi Key:Fill th\u1ea5p 1,3:1 \u2013 2,5:1 \u2013 m\u1eb7t s\u00e1ng \u0111\u1ec1u, \u00edt b\u00f3ng.',h:'Nh\u01b0 Loop nh\u01b0ng t\u0103ng fill g\u1ea7n b\u1eb1ng key.'},\n {id:'remd',p:'rembrandt',r:[8,99],t:'Rembrandt t\u1ed1i (low-key)',g:'Ra ki\u1ec3u Rembrandt v\u1edbi Key:Fill t\u1eeb 8:1 \u2013 t\u1ed1i, nhi\u1ec1u kh\u1ed1i.',h:'Gi\u1eef key ki\u1ec3u Rembrandt, gi\u1ea3m h\u1eb3n fill.'}];\nvar NAME={loop:'Loop',rembrandt:'Rembrandt',butterfly:'Butterfly',clamshell:'Clamshell',split:'Split',rim:'Ng\u01b0\u1ee3c s\u00e1ng',flat:'S\u00e1ng ph\u1eb3ng',none:'Ch\u01b0a c\u00f3 \u0111\u00e8n ch\u00ednh'};\nfunction vnDay(t){var d=new Date((t||Date.now())+7*3600e3);return d.toISOString().slice(0,10)}\nfunction dayIdx(){return Math.floor((Date.now()+7*3600e3)\/864e5)}\nfunction today(){return C[dayIdx()%C.length]}\nfunction S(){try{return JSON.parse(localStorage.getItem('kb_lab_day')||'{}')}catch(e){return {}}}\nfunction W(o){try{localStorage.setItem('kb_lab_day',JSON.stringify(o))}catch(e){}}\nfunction detect(){try{if(typeof ST==='undefined'||typeof keyL!=='function'||typeof geo!=='function')return null;if(ST.subj&&ST.subj.type==='product')return null;var k=keyL();if(!k)return{p:'none',r:NaN};\n var a=Math.abs(wrapAz(k.az)),G=geo(),dh=k.height-G.faceY,p;\n var fillLow=ST.lights.some(function(L){return L.on&&L.role==='fill'&&L.height<G.faceY-0.05&&Math.abs(wrapAz(L.az))<25});\n if(a>110)p='rim';else if(a>60)p='split';else if(a>35)p=(dh>=0.3&&dh<=0.9)?'rembrandt':'flat';else if(a>12)p='loop';else if(dh>=0.25)p=fillLow?'clamshell':'butterfly';else p='flat';\n var r=NaN;try{r=ratioKF(meter())}catch(e){} if(!isFinite(r)||r<=0)r=Infinity;return{p:p,r:r}}catch(e){return null}}\nfunction ok(c,d){if(!d||d.p!==c.p)return false;if(c.p==='rim')return true;return d.r>=c.r[0]&&(c.r[1]>=99||d.r<=c.r[1])}\nfunction rtxt(r){return !isFinite(r)?'kh\u00f4ng fill':(r>=10?Math.round(r):r.toFixed(1))+':1'}\nvar held=0,open=false,last='';\nfunction css(){if(document.getElementById('kbDayCss'))return;var s=document.createElement('style');s.id='kbDayCss';s.textContent=\n'#kbDay{position:absolute;z-index:6;padding:6px 10px;border-radius:10px;background:rgba(8,10,18,.82);border:1px solid rgba(79,139,255,.45);font:600 11.5px\/1.35 Montserrat,system-ui,sans-serif;color:#cfe0ff;cursor:pointer;backdrop-filter:blur(6px);text-align:left;max-width:280px}'+\n'#kbDay.done{border-color:rgba(47,210,122,.55);color:#bff3d6}'+\n'#kbDayP{position:fixed;z-index:99990;left:50%;top:50%;transform:translate(-50%,-50%);width:min(420px,calc(100vw - 32px));max-height:calc(100vh - 40px);overflow:auto;background:#0b1020;border:1px solid rgba(79,139,255,.35);border-radius:18px;padding:18px;color:#e8ecf6;font:14px\/1.55 Montserrat,system-ui,sans-serif;box-shadow:0 20px 60px rgba(0,0,0,.6)}'+\n'#kbDayP h4{margin:0 0 4px;font-size:16px;color:#fff}#kbDayP .k{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:#7ad7ff;font-weight:700}'+\n'#kbDayP .st{margin:12px 0;padding:10px 12px;border-radius:12px;background:#121a33;border:1px solid rgba(255,255,255,.08);font-size:13px}'+\n'#kbDayP .st b.y{color:#2fd27a}#kbDayP .st b.n{color:#9fb8ff}#kbDayP .h{font-size:12.5px;color:rgba(226,233,255,.7)}'+\n'#kbDayP .row{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}#kbDayP button{min-height:44px;padding:0 16px;border-radius:12px;border:1px solid rgba(79,139,255,.45);background:transparent;color:#cfe0ff;font:700 13.5px Montserrat,system-ui,sans-serif;cursor:pointer}'+\n'#kbDayP button.pri{background:#4f8bff;border-color:#4f8bff;color:#fff}#kbDayP button:disabled{opacity:.45;cursor:default}'+\n'#kbDayX{position:fixed;inset:0;z-index:99989;background:rgba(0,0,0,.55)}#kbDayP img{width:100%;border-radius:12px;margin-top:12px;display:block}';document.head.appendChild(s)}\nfunction streak(o){var t=vnDay(),y=vnDay(Date.now()-864e5);if(o.last===t||o.last===y)return o.streak||0;return 0}\nfunction tick(){try{var m=document.getElementById('meter'),pt=document.getElementById('kbPat');if(!m||!m.offsetParent)return;var d=detect();var b=document.getElementById('kbDay');\n if(!d){if(b)b.style.display='none';return}css();\n if(!b){b=document.createElement('button');b.type='button';b.id='kbDay';b.onclick=function(){open=true;panel()};m.parentNode.appendChild(b)}\n var ref=pt&&pt.offsetParent?pt:m;b.style.left=ref.offsetLeft+'px';b.style.top=(ref.offsetTop+ref.offsetHeight+6)+'px';b.style.display='';\n var c=today(),o=S(),done=o.done&&o.done[vnDay()]===c.id,good=ok(c,d);\n if(!done&&good){held+=0.6;if(held>=2){o.done=o.done||{};var keep={};Object.keys(o.done).sort().slice(-40).forEach(function(k){keep[k]=o.done[k]});o.done=keep;o.done[vnDay()]=c.id;o.streak=streak(o)+1;o.last=vnDay();o.best=Math.max(o.best||0,o.streak);o.res={p:d.p,r:isFinite(d.r)?d.r:null,at:Date.now()};W(o);done=true;open=true;panel(true)}}else held=0;\n var h=done?'Th\u1eed th\u00e1ch h\u00f4m nay: \u0111\u00e3 xong \u00b7 chu\u1ed7i '+(o.streak||1)+' ng\u00e0y':'Th\u1eed th\u00e1ch h\u00f4m nay: '+c.t+(good?' \u00b7 gi\u1eef nguy\u00ean\u2026':'');\n b.className=done?'done':'';if(b.__h!==h){b.textContent=h;b.__h=h}\n if(open&&document.getElementById('kbDayP'))live(c,d,done)}catch(e){}}\nfunction live(c,d,done){var e=document.getElementById('kbDaySt');if(!e)return;var good=ok(c,d);var h='Hi\u1ec7n t\u1ea1i: <b class=\"'+(d.p===c.p?'y':'n')+'\">'+NAME[d.p]+'<\/b> \u00b7 Key:Fill <b class=\"'+(good?'y':'n')+'\">'+rtxt(d.r)+'<\/b>'+(done?'<br><b class=\"y\">\u0110\u00e3 ho\u00e0n th\u00e0nh h\u00f4m nay<\/b>':good?'<br><b class=\"y\">\u0110\u00fang r\u1ed3i \u2013 gi\u1eef nguy\u00ean 2 gi\u00e2y<\/b>':'');if(e.__h!==h){e.innerHTML=h;e.__h=h}}\nfunction close(){var p=document.getElementById('kbDayP'),x=document.getElementById('kbDayX');p&&p.remove();x&&x.remove();open=false}\nfunction panel(justDone){close();open=true;var c=today(),o=S(),done=o.done&&o.done[vnDay()]===c.id;\n var x=document.createElement('div');x.id='kbDayX';x.onclick=close;document.body.appendChild(x);\n var p=document.createElement('div');p.id='kbDayP';p.setAttribute('role','dialog');p.setAttribute('aria-label','Th\u1eed th\u00e1ch \u00e1nh s\u00e1ng h\u00f4m nay');\n p.innerHTML='<div class=\"k\">Th\u1eed th\u00e1ch h\u00f4m nay \u00b7 '+vnDay().split('-').reverse().join('\/')+'<\/div><h4>'+c.t+'<\/h4><div>'+c.g+'<\/div><div class=\"h\" style=\"margin-top:6px\">G\u1ee3i \u00fd: '+c.h+'<\/div><div class=\"st\" id=\"kbDaySt\"><\/div>'+\n '<div class=\"h\">Chu\u1ed7i hi\u1ec7n t\u1ea1i: <b style=\"color:#fff\">'+streak(o)+' ng\u00e0y<\/b> \u00b7 d\u00e0i nh\u1ea5t: '+(o.best||0)+' ng\u00e0y. M\u1ed7i ng\u00e0y m\u1ed9t b\u00e0i m\u1edbi, l\u00e0m li\u00ean t\u1ee5c \u0111\u1ec3 gi\u1eef chu\u1ed7i.<\/div>'+\n '<div class=\"row\">'+(done?'<button class=\"pri\" id=\"kbDayCard\">T\u1ea1o th\u1ebb k\u1ebft qu\u1ea3 \u0111\u1ec3 chia s\u1ebb<\/button>':'')+'<button id=\"kbDayClose\">'+(done?'\u0110\u00f3ng':'B\u1eaft \u0111\u1ea7u setup')+'<\/button><\/div><div id=\"kbDayOut\"><\/div>';\n document.body.appendChild(p);p.querySelector('#kbDayClose').onclick=close;var cb=p.querySelector('#kbDayCard');if(cb)cb.onclick=card;\n var d=detect();if(d)live(c,d,done)}\nfunction card(){var btn=document.getElementById('kbDayCard');if(btn){btn.disabled=true;btn.textContent='\u0110ang t\u1ea1o th\u1ebb\u2026'}\n var c=today(),o=S(),res=o.res||{},W1=1080,H1=1350,cv=document.createElement('canvas');cv.width=W1;cv.height=H1;var g=cv.getContext('2d');\n var bg=g.createLinearGradient(0,0,0,H1);bg.addColorStop(0,'#0b1430');bg.addColorStop(1,'#05070d');g.fillStyle=bg;g.fillRect(0,0,W1,H1);\n var shot=null;try{var R=(typeof S3!=='undefined'&&S3.renderer)?S3.renderer.domElement:null;if(R&&R.width>10)shot=R}catch(e){}\n function txt(s,x,y,f,col,al){g.font=f;g.fillStyle=col;g.textAlign=al||'left';g.fillText(s,x,y)}\n var y0=230;if(shot){var bw=W1-120,bh=Math.round(bw*shot.height\/shot.width);if(bh>700){bh=700;bw=Math.round(bh*shot.width\/shot.height)}var bx=(W1-bw)\/2;g.save();g.beginPath();if(g.roundRect)g.roundRect(bx,y0,bw,bh,28);else g.rect(bx,y0,bw,bh);g.clip();try{g.drawImage(shot,bx,y0,bw,bh)}catch(e){}g.restore();g.strokeStyle='rgba(79,139,255,.5)';g.lineWidth=3;g.beginPath();if(g.roundRect)g.roundRect(bx,y0,bw,bh,28);else g.rect(bx,y0,bw,bh);g.stroke();y0+=bh+70}else y0+=60;\n txt('TH\u1eec TH\u00c1CH \u00c1NH S\u00c1NG \u00b7 '+vnDay().split('-').reverse().join('\/'),60,y0,'700 30px Montserrat, sans-serif','#7ad7ff');\n txt(c.t,60,y0+70,'800 58px Montserrat, sans-serif','#ffffff');\n txt('Ki\u1ec3u s\u00e1ng: '+(NAME[res.p]||'')+'   \u00b7   Key:Fill '+(res.r?rtxt(res.r):'kh\u00f4ng fill'),60,y0+130,'600 34px Montserrat, sans-serif','#cfe0ff');\n txt('Chu\u1ed7i '+(o.streak||1)+' ng\u00e0y li\u00ean t\u1ee5c',60,y0+185,'600 34px Montserrat, sans-serif','#9fb8ff');\n g.fillStyle='rgba(79,139,255,.18)';g.fillRect(0,H1-120,W1,120);txt('T\u1ef1 setup \u0111\u00e8n studio mi\u1ec5n ph\u00ed t\u1ea1i kblack.vn\/photo-lab',W1\/2,H1-48,'600 32px Montserrat, sans-serif','#ffffff','center');\n var lg=new Image();lg.crossOrigin='anonymous';var fin=function(){var out=document.getElementById('kbDayOut');cv.toBlob(function(b){if(!b){if(btn){btn.disabled=false;btn.textContent='T\u1ea1o th\u1ebb k\u1ebft qu\u1ea3 \u0111\u1ec3 chia s\u1ebb'}return}var u=URL.createObjectURL(b),f=null;try{f=new File([b],'kblack-photolab-'+vnDay()+'.png',{type:'image\/png'})}catch(e){}\n  if(out){out.innerHTML='<img decoding=\"async\" alt=\"Th\u1ebb k\u1ebft qu\u1ea3 th\u1eed th\u00e1ch \u00e1nh s\u00e1ng\" src=\"'+u+'\"><div class=\"row\"><button class=\"pri\" id=\"kbDayShare\">Chia s\u1ebb<\/button><button id=\"kbDaySave\">T\u1ea3i \u1ea3nh v\u1ec1<\/button><\/div>'}\n  if(btn)btn.remove();var sv=document.getElementById('kbDaySave');sv&&(sv.onclick=function(){var a=document.createElement('a');a.href=u;a.download='kblack-photolab-'+vnDay()+'.png';document.body.appendChild(a);a.click();a.remove()});\n  var sh=document.getElementById('kbDayShare');if(sh){if(f&&navigator.canShare&&navigator.canShare({files:[f]}))sh.onclick=function(){navigator.share({files:[f],title:'Th\u1eed th\u00e1ch \u00e1nh s\u00e1ng K-BLACK',text:'M\u00ecnh v\u1eeba setup '+c.t+' tr\u00ean K-BLACK Photo Lab \u2013 th\u1eed t\u1ea1i kblack.vn\/photo-lab'}).catch(function(){})};else sh.remove()}},'image\/png')};\n lg.onload=function(){var lw=240,lh=Math.round(lw*lg.height\/lg.width);g.drawImage(lg,(W1-lw)\/2,40,lw,lh);fin()};lg.onerror=fin;lg.src='\/wp-content\/uploads\/2024\/08\/4.-Main-Logo-Ca-Nhan-Mau-trang-.png'}\naddEventListener('keydown',function(e){if(e.key==='Escape'&&open)close()});\nsetInterval(tick,600);})();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Photo Lab \u2013 H\u1ecdc nhi\u1ebfp \u1ea3nh mi\u1ec5n ph\u00ed online &amp; m\u00f4 ph\u1ecfng \u00e1nh s\u00e1ng studio 3D K-BLACK Photo Lab Photo Lab 1T\u00e2n binh0 XP H\u1ecdc nhi\u1ebfp \u1ea3nh Studio \u00e1nh s\u00e1ng 3D T\u00e0i nguy\u00ean \u21b6 \u21b7 Ph\u00edm t\u1eaft L\u01b0u setup Setup \u0111\u00e3 l\u01b0u \u2630B\u00e0i h\u1ecdc\u2039\u203a \u2715 \u0110\u00f3ng Tr\u1ee3 l\u00fd K-BLACKH\u1ecdc xong m\u1ed7i b\u00e0i +40 XP. V\u00e0o [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-5391","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/kblack.vn\/en\/wp-json\/wp\/v2\/pages\/5391","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kblack.vn\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/kblack.vn\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/kblack.vn\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kblack.vn\/en\/wp-json\/wp\/v2\/comments?post=5391"}],"version-history":[{"count":1,"href":"https:\/\/kblack.vn\/en\/wp-json\/wp\/v2\/pages\/5391\/revisions"}],"predecessor-version":[{"id":7298,"href":"https:\/\/kblack.vn\/en\/wp-json\/wp\/v2\/pages\/5391\/revisions\/7298"}],"wp:attachment":[{"href":"https:\/\/kblack.vn\/en\/wp-json\/wp\/v2\/media?parent=5391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}