Plugin Directory

Changeset 3763637


Ignore:
Timestamp:
10/24/2026 06:25:14 PM (18 hours ago)
Author:
indiatvdna
Message:

Update trunk for version 1.4.9

Location:
indiatvdna-turbo-cache-lite/trunk
Files:
93 added
5 edited

Legend:

Unmodified
Added
Removed
  • indiatvdna-turbo-cache-lite/trunk/assets/admin.css

    r3729643 r3763637  
    1 .itdna-wrap{margin:0 0 0 -20px;background:#f4f7fb;min-height:calc(100vh - 32px);font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#172033}.itdna-shell{display:grid;grid-template-columns:245px minmax(0,1fr);min-height:calc(100vh - 32px)}.itdna-sidebar{background:#0b1731;color:#fff;padding:24px 14px;position:sticky;top:32px;height:calc(100vh - 32px);box-sizing:border-box;overflow:auto}.itdna-brand{display:flex;gap:11px;align-items:center;padding:0 10px 12px}.itdna-logo{display:grid;place-items:center;width:42px;height:42px;border-radius:13px;background:linear-gradient(135deg,#ffb000,#ff5c00);box-shadow:0 10px 24px rgba(255,122,0,.25);font-size:22px}.itdna-brand div{display:flex;flex-direction:column;line-height:1.15}.itdna-brand b{font-size:11px;letter-spacing:.12em;color:#8ba6d4;text-transform:uppercase}.itdna-brand strong{font-size:18px}.itdna-version{margin:0 10px 20px;padding:8px 10px;border-radius:8px;background:#102447;color:#93abd0;font-size:11px}.itdna-sidebar nav{display:flex;flex-direction:column;gap:4px}.itdna-sidebar nav a{display:flex;gap:10px;align-items:center;color:#aebfda;text-decoration:none;padding:10px 11px;border-radius:9px;font-size:13px;font-weight:600;transition:.15s}.itdna-sidebar nav a:hover,.itdna-sidebar nav a.active{background:#152b52;color:#fff}.itdna-sidebar nav a.active{box-shadow:inset 3px 0 #5aa3ff}.itdna-sidebar nav a span{width:18px;text-align:center}.itdna-side-status{margin:18px 10px 0;padding:11px;border-top:1px solid #21365c;color:#9fb2ce;font-size:12px}.dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#6b7891;margin-right:6px}.dot.on{background:#30d59d;box-shadow:0 0 0 4px rgba(48,213,157,.12)}.itdna-main{padding:28px 34px 90px;max-width:1250px;width:100%;box-sizing:border-box}.itdna-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.itdna-top h1{font-size:29px;margin:0;color:#121a2c}.itdna-top p{margin:6px 0 0;color:#71809a}.itdna-inline-form{display:inline-block;margin:0 6px 6px 0}.itdna-notice{padding:12px 15px;border-radius:10px;margin:0 0 18px;border:1px solid}.itdna-notice.success{background:#edfff7;border-color:#b6efd6;color:#11653f}.itdna-notice.error{background:#fff1f1;border-color:#ffc9c9;color:#9c2828}.itdna-grid-4{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px;margin-bottom:16px}.itdna-metric,.itdna-card{background:#fff;border:1px solid #e3e9f2;border-radius:14px;box-shadow:0 4px 18px rgba(35,55,90,.045)}.itdna-metric{padding:17px 18px}.itdna-metric span{font-size:12px;color:#8090aa;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.itdna-metric strong{display:block;font-size:23px;margin:7px 0 3px;color:#15213a}.itdna-metric small{color:#7f8ca2}.itdna-card{margin-bottom:16px}.itdna-card-head{padding:18px 20px;border-bottom:1px solid #edf1f6}.itdna-card-head h2{font-size:17px;margin:0;color:#17233b}.itdna-card-head p{margin:5px 0 0;color:#7c89a0;font-size:13px}.itdna-card-body{padding:18px 20px}.itdna-toggle-row{display:flex;justify-content:space-between;gap:20px;align-items:center;padding:13px 0;border-bottom:1px solid #eff3f7}.itdna-toggle-row:last-child{border-bottom:0}.itdna-toggle-row span:first-child{display:flex;flex-direction:column;gap:4px}.itdna-toggle-row strong,.itdna-field strong{font-size:14px;color:#17233b}.itdna-toggle-row small,.itdna-field small{display:block;color:#8290a7;font-size:12px;font-weight:400;line-height:1.4}.itdna-risk{font-style:normal;font-size:10px;font-weight:700;color:#a76300;background:#fff4d7;border:1px solid #ffe5a0;border-radius:999px;padding:2px 7px;width:max-content}.itdna-switch{position:relative;min-width:44px;height:24px}.itdna-switch input{position:absolute;opacity:0}.itdna-switch i{position:absolute;inset:0;background:#c8d1df;border-radius:999px;cursor:pointer;transition:.2s}.itdna-switch i:after{content:"";position:absolute;width:18px;height:18px;left:3px;top:3px;background:#fff;border-radius:50%;box-shadow:0 2px 4px rgba(0,0,0,.2);transition:.2s}.itdna-switch input:checked+i{background:#2f80ed}.itdna-switch input:checked+i:after{transform:translateX(20px)}.itdna-field{margin:0 0 15px}.itdna-field label{display:block}.itdna-field input[type=text],.itdna-field input[type=url],.itdna-field input[type=password],.itdna-field input[type=number],.itdna-field textarea,.itdna-field select{margin-top:8px;width:100%;max-width:760px;border:1px solid #cfd8e6;border-radius:8px;min-height:40px;padding:8px 10px;background:#fff;box-shadow:none}.itdna-field textarea{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.itdna-checklist{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.itdna-checklist div{padding:11px 12px;border-radius:9px;background:#f6fbff;color:#365273;border:1px solid #e4f1ff}.itdna-actions{display:flex;flex-wrap:wrap;gap:4px}.itdna-help,.itdna-info{color:#738198;font-size:12px}.itdna-db-row{display:flex;align-items:center;gap:10px;padding:12px 4px;border-bottom:1px solid #edf1f6}.itdna-db-row input{margin:0}.itdna-db-row span{display:flex;gap:7px;align-items:baseline}.itdna-db-row small{color:#8896ac}.itdna-savebar{position:sticky;bottom:0;display:flex;justify-content:space-between;align-items:center;padding:12px 16px;background:rgba(255,255,255,.96);backdrop-filter:blur(8px);border:1px solid #dfe7f1;border-radius:12px;box-shadow:0 -4px 20px rgba(29,44,73,.08);z-index:20}.itdna-savebar span{color:#748198;font-size:12px}.itdna-diagnostic{display:grid;grid-template-columns:12px minmax(180px,1fr) minmax(220px,2fr);align-items:center;gap:10px;padding:11px 2px;border-bottom:1px solid #edf1f6}.itdna-diagnostic .status{width:9px;height:9px;border-radius:50%;background:#abb5c6}.itdna-diagnostic .status.ok{background:#26bf83}.itdna-diagnostic .status.warn{background:#ffb020}.itdna-diagnostic .status.bad{background:#ef5b5b}.itdna-diagnostic small{color:#8290a7}@media(max-width:1000px){.itdna-shell{grid-template-columns:190px 1fr}.itdna-main{padding:22px}.itdna-grid-4{grid-template-columns:repeat(2,1fr)}.itdna-checklist{grid-template-columns:1fr}}@media(max-width:782px){.itdna-wrap{margin-left:-10px}.itdna-shell{display:block}.itdna-sidebar{position:relative;top:auto;height:auto}.itdna-sidebar nav{display:grid;grid-template-columns:repeat(2,1fr)}.itdna-main{padding:16px}.itdna-top{align-items:flex-start;gap:10px}.itdna-grid-4{grid-template-columns:1fr}.itdna-diagnostic{grid-template-columns:12px 1fr}.itdna-diagnostic small{grid-column:2}.itdna-savebar{bottom:0}.itdna-checklist{grid-template-columns:1fr}}
     1.itdna-wrap{margin:0 0 0 -20px;padding:10px 0 0 10px;background:#f4f7fb;min-height:calc(100vh - 32px);box-sizing:border-box;font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#172033}.itdna-shell{display:grid;grid-template-columns:245px minmax(0,1fr);column-gap:10px;min-height:calc(100vh - 42px)}.itdna-sidebar{background:linear-gradient(180deg,#0b1731 0%,#0a1630 100%);color:#fff;padding:24px 14px;position:sticky;top:42px;height:calc(100vh - 52px);box-sizing:border-box;overflow:auto;border-radius:16px;box-shadow:0 10px 28px rgba(16,34,66,.12);border:1px solid rgba(255,255,255,.06)}.itdna-brand{display:flex;gap:11px;align-items:center;padding:0 10px 12px}.itdna-logo{display:grid;place-items:center;width:42px;height:42px;border-radius:13px;background:linear-gradient(135deg,#ffb000,#ff5c00);box-shadow:0 10px 24px rgba(255,122,0,.25);font-size:22px}.itdna-brand div{display:flex;flex-direction:column;line-height:1.15}.itdna-brand b{font-size:11px;letter-spacing:.12em;color:#8ba6d4;text-transform:uppercase}.itdna-brand strong{font-size:18px}.itdna-version{margin:0 10px 20px;padding:8px 10px;border-radius:8px;background:#102447;color:#93abd0;font-size:11px}.itdna-sidebar nav{display:flex;flex-direction:column;gap:4px}.itdna-sidebar nav a{display:flex;gap:10px;align-items:center;color:#aebfda;text-decoration:none;padding:10px 11px;border-radius:9px;font-size:13px;font-weight:600;transition:.15s}.itdna-sidebar nav a:hover,.itdna-sidebar nav a.active{background:#152b52;color:#fff}.itdna-sidebar nav a.active{box-shadow:inset 3px 0 #5aa3ff}.itdna-sidebar nav a span{width:18px;text-align:center}.itdna-side-status{margin:18px 10px 0;padding:11px;border-top:1px solid #21365c;color:#9fb2ce;font-size:12px}.dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#6b7891;margin-right:6px}.dot.on{background:#30d59d;box-shadow:0 0 0 4px rgba(48,213,157,.12)}.itdna-main{padding:28px 34px 90px;max-width:1250px;width:100%;box-sizing:border-box}.itdna-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.itdna-top h1{font-size:29px;margin:0;color:#121a2c}.itdna-top p{margin:6px 0 0;color:#71809a}.itdna-inline-form{display:inline-block;margin:0 6px 6px 0}.itdna-notice{padding:12px 15px;border-radius:10px;margin:0 0 18px;border:1px solid}.itdna-notice.success{background:#edfff7;border-color:#b6efd6;color:#11653f}.itdna-notice.error{background:#fff1f1;border-color:#ffc9c9;color:#9c2828}.itdna-grid-4{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px;margin-bottom:16px}.itdna-metric,.itdna-card{background:#fff;border:1px solid #e3e9f2;border-radius:14px;box-shadow:0 4px 18px rgba(35,55,90,.045)}.itdna-metric{padding:17px 18px}.itdna-metric span{font-size:12px;color:#8090aa;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.itdna-metric strong{display:block;font-size:23px;margin:7px 0 3px;color:#15213a}.itdna-metric small{color:#7f8ca2}.itdna-card{margin-bottom:16px}.itdna-card-head{padding:18px 20px;border-bottom:1px solid #edf1f6}.itdna-card-head h2{font-size:17px;margin:0;color:#17233b}.itdna-card-head p{margin:5px 0 0;color:#7c89a0;font-size:13px}.itdna-card-body{padding:18px 20px}.itdna-toggle-row{display:flex;justify-content:space-between;gap:20px;align-items:center;padding:13px 0;border-bottom:1px solid #eff3f7}.itdna-toggle-row:last-child{border-bottom:0}.itdna-toggle-row span:first-child{display:flex;flex-direction:column;gap:4px}.itdna-toggle-row strong,.itdna-field strong{font-size:14px;color:#17233b}.itdna-toggle-row small,.itdna-field small{display:block;color:#8290a7;font-size:12px;font-weight:400;line-height:1.4}.itdna-risk{font-style:normal;font-size:10px;font-weight:700;color:#a76300;background:#fff4d7;border:1px solid #ffe5a0;border-radius:999px;padding:2px 7px;width:max-content}.itdna-switch{position:relative;min-width:44px;height:24px}.itdna-switch input{position:absolute;opacity:0}.itdna-switch i{position:absolute;inset:0;background:#c8d1df;border-radius:999px;cursor:pointer;transition:.2s}.itdna-switch i:after{content:"";position:absolute;width:18px;height:18px;left:3px;top:3px;background:#fff;border-radius:50%;box-shadow:0 2px 4px rgba(0,0,0,.2);transition:.2s}.itdna-switch input:checked+i{background:#2f80ed}.itdna-switch input:checked+i:after{transform:translateX(20px)}.itdna-field{margin:0 0 15px}.itdna-field label{display:block}.itdna-field input[type=text],.itdna-field input[type=url],.itdna-field input[type=password],.itdna-field input[type=number],.itdna-field textarea,.itdna-field select{margin-top:8px;width:100%;max-width:760px;border:1px solid #cfd8e6;border-radius:8px;min-height:40px;padding:8px 10px;background:#fff;box-shadow:none}.itdna-field textarea{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.itdna-checklist{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.itdna-checklist div{padding:11px 12px;border-radius:9px;background:#f6fbff;color:#365273;border:1px solid #e4f1ff}.itdna-actions{display:flex;flex-wrap:wrap;gap:4px}.itdna-help,.itdna-info{color:#738198;font-size:12px}.itdna-db-row{display:flex;align-items:center;gap:10px;padding:12px 4px;border-bottom:1px solid #edf1f6}.itdna-db-row input{margin:0}.itdna-db-row span{display:flex;gap:7px;align-items:baseline}.itdna-db-row small{color:#8896ac}.itdna-savebar{position:sticky;bottom:0;display:flex;justify-content:space-between;align-items:center;padding:12px 16px;background:rgba(255,255,255,.96);backdrop-filter:blur(8px);border:1px solid #dfe7f1;border-radius:12px;box-shadow:0 -4px 20px rgba(29,44,73,.08);z-index:20}.itdna-savebar span{color:#748198;font-size:12px}.itdna-diagnostic{display:grid;grid-template-columns:12px minmax(180px,1fr) minmax(220px,2fr);align-items:center;gap:10px;padding:11px 2px;border-bottom:1px solid #edf1f6}.itdna-diagnostic .status{width:9px;height:9px;border-radius:50%;background:#abb5c6}.itdna-diagnostic .status.ok{background:#26bf83}.itdna-diagnostic .status.info{background:#6f86a8}.itdna-diagnostic .status.warn{background:#ffb020}.itdna-diagnostic .status.bad{background:#ef5b5b}.itdna-diagnostic small{color:#8290a7}@media(max-width:1000px){.itdna-wrap{padding-left:8px;padding-top:8px}.itdna-shell{grid-template-columns:190px 1fr;column-gap:8px}.itdna-sidebar{top:40px;height:calc(100vh - 48px)}.itdna-main{padding:22px}.itdna-grid-4{grid-template-columns:repeat(2,1fr)}.itdna-checklist{grid-template-columns:1fr}}@media(max-width:782px){.itdna-wrap{margin-left:-10px;padding-left:6px;padding-top:6px}.itdna-shell{display:block}.itdna-sidebar{position:relative;top:auto;height:auto;border-radius:14px}.itdna-sidebar nav{display:grid;grid-template-columns:repeat(2,1fr)}.itdna-main{padding:16px}.itdna-top{align-items:flex-start;gap:10px}.itdna-grid-4{grid-template-columns:1fr}.itdna-diagnostic{grid-template-columns:12px 1fr}.itdna-diagnostic small{grid-column:2}.itdna-savebar{bottom:0}.itdna-checklist{grid-template-columns:1fr}}
    22
    33.itdna-engine-note{padding:12px 14px;border-radius:10px;background:#f6f9ff;border:1px solid #e2ebfa;color:#52627a}.itdna-diagnostic strong{font-weight:700}.itdna-diagnostic small{line-height:1.45}.itdna-card .button-primary{box-shadow:0 5px 14px rgba(47,128,237,.14)}
    … …  
    189189
    190190
    191 
    192 /* Lite-only Full-style upgrade presentation */
    193 .itdna-sidebar nav a{position:relative}
    194 .itdna-sidebar nav a.is-pro-tab b{margin-left:auto;font-size:8px;line-height:1;padding:4px 5px;border-radius:999px;background:#eef2ff;color:#4f46e5;letter-spacing:.05em}
    195 .itdna-sidebar nav a.is-pro-tab.active b{background:rgba(255,255,255,.18);color:#fff}
    196 .itdna-mini-pro{display:inline-flex;margin-left:5px;padding:2px 5px;border-radius:999px;background:#fff2cd;color:#936400;font-size:9px;line-height:1;font-weight:800}
    197 .itdna-metric.is-pro{border-color:#ead9aa;background:linear-gradient(180deg,#fffdf7,#fff)}
    198 .itdna-pro-preview-head{display:flex;align-items:center;justify-content:space-between;gap:22px;padding:20px 22px;margin-bottom:12px;border-radius:14px;background:linear-gradient(135deg,#071a38,#173b69);box-shadow:0 8px 26px rgba(22,43,75,.08);color:#fff}
    199 .itdna-pro-preview-head h2{margin:5px 0 7px;color:#fff;font-size:20px!important;line-height:1.2!important}.itdna-pro-preview-head p{margin:0;max-width:780px;color:#c8d8ec;font-size:12px!important;line-height:1.5!important}
    200 .itdna-pro-badge{display:inline-flex;padding:5px 9px;border-radius:999px;background:#ffbd2e;color:#3a2a00;font-size:10px;font-weight:900;letter-spacing:.08em}
    201 .itdna-preview-note{margin:0 0 15px;padding:11px 14px;border:1px solid #f0d99b;border-radius:10px;background:#fff9e8;color:#6e581c;font-size:11.5px;line-height:1.45}
    202 .itdna-card-title-row{display:flex;align-items:center;justify-content:space-between;gap:14px}.itdna-pro-pill{display:inline-flex;padding:4px 8px;border-radius:999px;background:#171f2e;color:#fff;font-size:9px;font-weight:900;letter-spacing:.08em}.itdna-pro-card{border-top:3px solid #dca928}
    203 .itdna-feature-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.itdna-feature-list>div{display:flex;gap:9px;align-items:flex-start;padding:11px 12px;border:1px solid #e7ebf0;border-radius:9px;background:#fafbfd}.itdna-feature-list>div>span{width:20px;height:20px;border-radius:50%;display:grid;place-items:center;flex:none;background:#dff6e9;color:#168154;font-weight:900}.itdna-feature-list p{margin:1px 0 0;color:#4d5c70;font-size:12px;line-height:1.45}
    204 .itdna-card-upgrade{display:flex;align-items:center;justify-content:space-between;gap:14px;margin-top:16px;padding:12px 14px;border-radius:10px;background:#f7f9fc;border:1px solid #e4e9f0}.itdna-card-upgrade span{font-weight:700;color:#45536a;font-size:12px}
    205 .itdna-comparison{display:grid;grid-template-columns:1fr 1fr;gap:14px}.itdna-plan-box{border:1px solid #dfe5ed;border-radius:12px;padding:18px;background:#fff}.itdna-plan-box.featured{border:2px solid #2271b1;background:#f7fbff}.itdna-plan-label{display:inline-flex;padding:4px 8px;border-radius:999px;background:#edf1f5;color:#56677d;font-size:10px;font-weight:900;letter-spacing:.08em}.itdna-plan-box.featured .itdna-plan-label{background:#2271b1;color:#fff}.itdna-plan-box h3{font-size:16px!important;margin:10px 0}.itdna-plan-box ul{margin:0 0 16px 18px}.itdna-plan-box li{font-size:12px;line-height:1.45;margin:6px 0;color:#4f6075}
    206 .itdna-impact-disclaimer{margin:0 0 14px;padding:10px 12px;border:1px solid #d8e7f6;border-radius:9px;background:#f6fbff;color:#4b627c;font-size:11.5px;line-height:1.5}.itdna-impact{margin-top:14px;padding:10px 12px;border-radius:9px;background:#eff8f3;border:1px solid #cce8d8;color:#285b42;font-size:11.5px;line-height:1.45}
    207 .itdna-upgrade-hint{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:9px;align-items:start;margin:8px 0 12px;padding:9px 11px;border:1px solid #eadfb7;border-radius:9px;background:#fffaf0;color:#5a4b1f;font-size:11.5px;line-height:1.45}.itdna-upgrade-hint .itdna-mini-pro{margin:1px 0 0}.itdna-upgrade-hint a{font-weight:700;text-decoration:none;white-space:nowrap}.itdna-upgrade-hint small{font-size:11px;color:#756738}
    208 .itdna-pro-setting>a{flex:0 0 auto}.itdna-pro-db-row{opacity:.82}.itdna-result-banner{display:flex;flex-direction:column;gap:3px;margin:10px 0;padding:10px 12px;border:1px solid #dfe7f0;border-radius:9px;background:#f7f9fc}.itdna-result-banner.ok{background:#effcf6;border-color:#c9efdd;color:#155f42}.itdna-result-banner.warn{background:#fff8e9;border-color:#f4dfac;color:#7c5900}.itdna-result-banner small{font-size:11.5px;line-height:1.45}
    209 @media(max-width:900px){.itdna-pro-preview-head{display:block}.itdna-pro-preview-head .button{margin-top:14px}.itdna-feature-list,.itdna-comparison{grid-template-columns:1fr}.itdna-card-upgrade{align-items:flex-start;flex-direction:column}}
    210 @media(max-width:782px){.itdna-upgrade-hint{grid-template-columns:auto 1fr}.itdna-upgrade-hint>a{grid-column:2}}
     191/* v2.5.34 AR-6 asset-report visual hierarchy */
     192.itdna-asset-report{display:grid;gap:14px;margin:14px 0 2px}
     193.itdna-asset-section{overflow:hidden;border:1px solid #e2e9f2;border-radius:12px;background:#fff}
     194.itdna-asset-section-head{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:13px 15px;border-bottom:1px solid #e9eef5;background:#f8fafc}
     195.itdna-asset-section-head>div{min-width:0}
     196.itdna-asset-kicker{display:block;margin-bottom:2px;color:#75849a;font-size:9.5px;font-weight:800;letter-spacing:.075em;text-transform:uppercase}
     197.itdna-asset-section-head h3{margin:0;color:#17233b;font-size:14px;line-height:1.3;font-weight:650}
     198.itdna-integrity-badge{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;padding:5px 8px;border:1px solid;border-radius:999px;font-size:10px;line-height:1.2;font-weight:700;white-space:nowrap}
     199.itdna-integrity-badge span{font-weight:600;opacity:.76}
     200.itdna-integrity-badge strong{font-size:10px!important;line-height:1.2!important;font-weight:800!important;letter-spacing:.03em!important}
     201.itdna-integrity-badge.is-pass{border-color:#b9ead5;background:#effbf5;color:#177451}
     202.itdna-integrity-badge.is-fail{border-color:#ffcaca;background:#fff1f1;color:#a12f2f}
     203.itdna-integrity-badge.is-pending{border-color:#d8e1ec;background:#f5f7fa;color:#66758a}
     204.itdna-asset-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;padding:10px}
     205.itdna-asset-stat{min-width:0;min-height:78px;padding:10px 11px;border:1px solid #e4ebf3;border-radius:9px;background:#fbfdff;box-sizing:border-box}
     206.itdna-asset-stat-label{display:block;color:#50617a;font-size:11px;line-height:1.35;font-weight:650}
     207.itdna-asset-stat-value{display:block!important;margin:5px 0 2px!important;color:#17345e!important;font-size:18px!important;line-height:1.05!important;font-weight:600!important;letter-spacing:-.01em!important}
     208.itdna-asset-stat small{display:block;color:#8693a6;font-size:10px;line-height:1.35}
     209.itdna-asset-stat.is-secondary{background:#fcfdff}
     210.itdna-asset-stat.is-pending .itdna-asset-stat-value{color:#98a3b3!important}
     211.itdna-asset-stat.is-zero{border-color:#e8edf3;background:#fafbfc}
     212.itdna-asset-stat.is-zero .itdna-asset-stat-value{color:#8b98aa!important;font-weight:500!important}
     213.itdna-asset-stat.is-zero .itdna-asset-stat-label,.itdna-asset-stat.is-zero small{color:#8a96a7}
     214.itdna-asset-summary{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
     215.itdna-asset-summary>div{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:11px 13px;border:1px solid #dce8f5;border-radius:10px;background:#f5f9ff}
     216.itdna-asset-summary span{color:#51637c;font-size:11px;font-weight:650}
     217.itdna-asset-summary strong{color:#17345e!important;font-size:16px!important;line-height:1.1!important;font-weight:600!important;white-space:nowrap}
     218@media(max-width:1100px){.itdna-asset-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
     219@media(max-width:650px){.itdna-asset-section-head{align-items:flex-start}.itdna-asset-grid,.itdna-asset-summary{grid-template-columns:1fr}.itdna-asset-stat{min-height:0}.itdna-asset-summary>div{align-items:flex-start;flex-direction:column;gap:4px}}
     220.itdna-asset-explainer{display:grid;gap:5px;margin:10px 0 12px;padding:10px 12px;border:1px solid #e4ebf3;border-radius:9px;background:#fafcff;color:#718098;font-size:11px;line-height:1.45}
     221.itdna-asset-explainer span{display:block}
     222.itdna-asset-explainer b{color:#465870;font-size:inherit!important;line-height:inherit!important;font-weight:700}
     223.itdna-info strong,.itdna-help strong{display:inline!important;font-size:inherit!important;line-height:inherit!important;font-weight:700!important;letter-spacing:0!important}
     224
     225
     226/* v2.5.36 compact optimizer ownership / compatibility status */
     227.itdna-compat-status-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin-top:12px}
     228.itdna-compat-status{min-width:0;padding:10px 11px;border:1px solid #e4ebf3;border-radius:9px;background:#fbfdff}
     229.itdna-compat-label{display:block;margin-bottom:7px;color:#50617a;font-size:11px;line-height:1.3;font-weight:650}
     230.itdna-compat-badge{display:inline-flex;align-items:center;min-height:22px;padding:3px 8px;border:1px solid;border-radius:999px;font-size:10px;line-height:1.2;font-weight:750;white-space:nowrap}
     231.itdna-compat-badge.is-muted{border-color:#dfe5ed;background:#f5f7fa;color:#6f7d90}
     232.itdna-compat-badge.is-active{border-color:#b9ead5;background:#effbf5;color:#177451}
     233.itdna-compat-badge.is-owner{border-color:#c8ddf7;background:#f1f7ff;color:#255b9b}
     234.itdna-compat-badge.is-external{border-color:#ffe0a3;background:#fff8e8;color:#96620b}
     235.itdna-compat-status small{display:block;margin-top:6px;color:#8a96a7;font-size:10px;line-height:1.35}
     236@media(max-width:1000px){.itdna-compat-status-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
     237@media(max-width:560px){.itdna-compat-status-grid{grid-template-columns:1fr}}
     238/* v2.21 Safe Auto Settings */
     239.itdna-plan-row small{display:block;opacity:.72;font-size:11px;font-weight:700;margin-bottom:3px;letter-spacing:.02em}.itdna-auto-hero-actions{gap:8px;flex-wrap:wrap}.itdna-diagnostic .status.ok{background:#22c55e}.itdna-diagnostic .status.warn{background:#f59e0b}
     240
     241/* v2.23 Optimization Ownership Manager */
     242.itdna-toggle-row.itdna-toggle-standby{border-color:#f0d49a;background:#fffdf7}
     243.itdna-owner-standby-badge{display:inline-flex!important;align-items:center;margin-top:6px!important;padding:3px 7px!important;border:1px solid #f2d08a!important;border-radius:999px!important;background:#fff7df!important;color:#8a5a09!important;font-size:9.5px!important;line-height:1.2!important;font-style:normal!important;font-weight:800!important;letter-spacing:.035em!important}
     244.itdna-owner-inline{display:grid;gap:7px;margin:-3px 0 12px;padding:10px 12px;border:1px solid #f1d59b;border-left:4px solid #e5a72f;border-radius:9px;background:#fffaf0;font-size:11px;line-height:1.45;color:#59677a}
     245.itdna-owner-inline strong{font-size:11px!important;line-height:1.4!important;color:#2d3b4f!important;font-weight:750!important}
     246.itdna-owner-inline-main,.itdna-owner-inline-why{display:block}
     247.itdna-owner-inline-why{padding-top:6px;border-top:1px dashed #ecd9b3}
     248.itdna-owner-inline-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding-top:2px}
     249.itdna-owner-inline-actions .button{font-size:11px!important;min-height:28px!important;line-height:26px!important;padding:0 10px!important}
     250.itdna-owner-inline-actions small{flex:1;min-width:220px;color:#7b8798;font-size:10px!important;line-height:1.4!important}
     251.itdna-owner-situation{display:grid;gap:5px;margin:12px 0 4px;padding:10px 12px;border:1px solid #d8e5f4;border-radius:9px;background:#f7fbff;color:#52647d;font-size:11px;line-height:1.45}
     252.itdna-owner-situation>strong{font-size:11.5px!important;color:#214d82!important}
     253.itdna-owner-situation b{font-size:inherit!important;line-height:inherit!important;color:#34465d!important}
     254.itdna-owner-restore{margin-top:3px}
     255@media(max-width:650px){.itdna-owner-inline-actions{align-items:flex-start;flex-direction:column}.itdna-owner-inline-actions small{min-width:0}.itdna-owner-inline-actions .button{width:100%;text-align:center}}
     256
     257.itdna-server-badge{display:inline-flex;align-items:center;margin:6px 6px 0 0;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:800;letter-spacing:.03em;background:#eef2f7;color:#334155}
     258.itdna-server-recommended_on{background:#dcfce7;color:#166534}.itdna-server-background_only{background:#fef3c7;color:#92400e}.itdna-server-adaptive_off{background:#f1f5f9;color:#475569}.itdna-server-default_off{background:#f1f5f9;color:#475569}.itdna-server-conditional{background:#e0f2fe;color:#075985}.itdna-server-standby{background:#fef3c7;color:#92400e}.itdna-server-optional{background:#e0f2fe;color:#075985}
     259
     260.itdna-server-advisory{margin:8px 0 14px;padding:10px 12px;border-radius:10px;font-size:12px;line-height:1.45;background:#fff7ed;border:1px solid #fed7aa;color:#7c2d12}.itdna-server-advisory.default_off,.itdna-server-advisory.adaptive_off{background:#f8fafc;border-color:#e2e8f0;color:#475569}.itdna-server-advisory.conditional{background:#f0f9ff;border-color:#bae6fd;color:#075985}.itdna-server-advisory.standby{background:#fffbeb;border-color:#fde68a;color:#92400e}.itdna-server-advisory.recommended_on{background:#f0fdf4;border-color:#bbf7d0;color:#166534}
     261
     262.itdna-server-profile-card{border:1px solid #dbeafe}.itdna-server-profile-card .itdna-card-head{background:linear-gradient(135deg,#eff6ff,#f8fafc)}
     263
     264
     265/* v2.33.12 two-choice Auto Best launcher */
     266body.itdna-modal-open{overflow:hidden}
     267.itdna-auto-choice-modal[hidden]{display:none!important}.itdna-auto-choice-modal{position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;padding:24px;box-sizing:border-box}.itdna-auto-choice-backdrop{position:absolute;inset:0;background:rgba(8,20,42,.62);backdrop-filter:blur(3px)}.itdna-auto-choice-dialog{position:relative;z-index:1;width:min(920px,96vw);max-height:90vh;overflow:auto;background:#fff;border:1px solid #d9e3ef;border-radius:18px;box-shadow:0 24px 80px rgba(8,28,62,.28);padding:22px;box-sizing:border-box}.itdna-auto-choice-x{position:absolute;right:14px;top:12px;border:0;background:transparent;color:#64748b;font-size:28px;line-height:1;cursor:pointer}.itdna-auto-choice-head{padding:2px 32px 16px 2px}.itdna-auto-choice-head h2{margin:4px 0 7px;font-size:22px;line-height:1.25;color:#14213d}.itdna-auto-choice-head p{margin:0;color:#66758a;font-size:13px;line-height:1.55}.itdna-auto-choice-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}.itdna-auto-choice-card{appearance:none;width:100%;min-height:330px;text-align:left;border-radius:15px;padding:18px;border:2px solid;background:#fff;cursor:pointer;transition:transform .16s ease,box-shadow .16s ease,border-color .16s ease;display:flex;flex-direction:column;gap:10px;font-family:inherit}.itdna-auto-choice-card:hover{transform:translateY(-2px);box-shadow:0 10px 28px rgba(24,52,91,.12)}.itdna-auto-choice-card.is-green{border-color:#86d9ad;background:linear-gradient(180deg,#f1fcf6 0,#fff 54%)}.itdna-auto-choice-card.is-red{border-color:#f1aaaa;background:linear-gradient(180deg,#fff4f4 0,#fff 54%)}.itdna-auto-choice-card.is-green:hover{border-color:#22a45c}.itdna-auto-choice-card.is-red:hover{border-color:#d64d4d}.itdna-auto-choice-badge{display:inline-flex;align-self:flex-start;padding:4px 8px;border-radius:999px;font-size:10px;font-weight:850;letter-spacing:.04em}.is-green .itdna-auto-choice-badge{background:#d7f7e4;color:#13703c}.is-red .itdna-auto-choice-badge{background:#ffe0e0;color:#a72424}.itdna-auto-choice-card>strong{font-size:17px!important;line-height:1.3!important;color:#14213d!important}.itdna-auto-choice-card>p{margin:0;color:#526176;font-size:12.5px;line-height:1.55}.itdna-auto-choice-facts{display:grid;gap:5px;padding:10px 11px;border:1px solid #cfead9;border-radius:10px;background:#fff;color:#40536a;font-size:11px;line-height:1.42}.itdna-auto-choice-facts b{color:#193c2a}.itdna-auto-choice-warning{padding:11px 12px;border:1px solid #f4c3c3;border-radius:10px;background:#fff7f7;color:#8f2929;font-size:11.5px;line-height:1.5}.itdna-auto-choice-card em{margin-top:auto;color:#6b788a;font-size:10.5px;line-height:1.45;font-style:normal}.itdna-auto-choice-foot{display:flex;align-items:center;gap:12px;margin-top:16px;padding-top:14px;border-top:1px solid #e8edf3}.itdna-auto-choice-foot small{color:#7c899a;font-size:11px}.itdna-auto-choice-foot .button{margin-left:auto}
     268@media(max-width:760px){.itdna-auto-choice-modal{padding:10px}.itdna-auto-choice-dialog{padding:16px}.itdna-auto-choice-grid{grid-template-columns:1fr}.itdna-auto-choice-card{min-height:0}.itdna-auto-choice-foot{align-items:flex-start;flex-direction:column}.itdna-auto-choice-foot .button{margin-left:0;width:100%}}
     269.itdna-performance-flow-status{display:inline-flex;align-items:center;min-height:32px;color:#71809a;font-size:12px;margin-left:8px}.itdna-performance-flow-progress{margin-top:10px;height:6px;background:#e7edf7;border-radius:999px;overflow:hidden}.itdna-performance-flow-progress[hidden]{display:none}.itdna-performance-flow-progress>div{height:100%;width:0;background:#2f80ed;border-radius:999px;transition:width .3s ease}
     270
     271/* v2.33.17 Zero-Touch Easy Auto Setup */
     272.itdna-easy-setup{margin:0 0 16px;padding:18px;border:1px solid #d7e4f2;border-radius:14px;background:linear-gradient(180deg,#f8fbff,#fff);box-shadow:0 4px 18px rgba(24,52,91,.05)}
     273.itdna-easy-head{display:flex;align-items:flex-start;justify-content:space-between;gap:18px}.itdna-easy-head h2{margin:4px 0 6px;color:#14213d;font-size:20px;line-height:1.25}.itdna-easy-head p{max-width:940px;margin:0;color:#617089;font-size:12.5px;line-height:1.55}.itdna-easy-badge{flex:0 0 auto;padding:6px 9px;border-radius:999px;background:#e9f3ff;color:#215992;font-size:10px;font-weight:800;letter-spacing:.035em}.itdna-easy-setup[data-status="running"] .itdna-easy-badge{background:#e6f8ee;color:#167047}.itdna-easy-setup[data-status="complete"] .itdna-easy-badge{background:#dff7e9;color:#12683f}.itdna-easy-setup[data-status="attention"] .itdna-easy-badge,.itdna-easy-setup[data-status="superseded"] .itdna-easy-badge{background:#fff1db;color:#8a5700}
     274.itdna-easy-progress{height:8px;margin:14px 0 10px;overflow:hidden;border-radius:999px;background:#e8eef6}.itdna-easy-progress i{display:block;height:100%;border-radius:999px;background:linear-gradient(90deg,#2d6cdf,#36a56f);transition:width .35s ease}
     275.itdna-easy-status{display:grid;grid-template-columns:auto auto 1fr;align-items:center;gap:9px;color:#52647d}.itdna-easy-status>strong{color:#1d3558;font-size:12px!important}.itdna-easy-status>span{padding:2px 7px;border-radius:999px;background:#edf3fb;color:#315a8e;font-size:10px;font-weight:800}.itdna-easy-status>p{grid-column:1/-1;margin:0;color:#6b788a;font-size:11.5px;line-height:1.45}
     276.itdna-easy-steps{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:7px;margin:12px 0}.itdna-easy-steps span{padding:7px 8px;border:1px solid #e1e8f1;border-radius:8px;background:#fbfdff;color:#617089;font-size:10px;font-weight:650;text-align:center}
     277.itdna-easy-compare{overflow:hidden;border:1px solid #e1e8f1;border-radius:10px;background:#fff}.itdna-easy-compare-head,.itdna-easy-compare-row{display:grid;grid-template-columns:1.5fr 1fr 1fr;gap:12px;align-items:center;padding:9px 11px}.itdna-easy-compare-head{background:#f6f9fd;border-bottom:1px solid #e1e8f1;color:#64748b;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.04em}.itdna-easy-compare-row{border-bottom:1px solid #edf1f6;color:#52647d;font-size:11px}.itdna-easy-compare-row:last-child{border-bottom:0}.itdna-easy-compare-row>strong{color:#193c68!important;font-size:12px!important;font-weight:750!important}
     278.itdna-easy-verdict{margin-top:12px;padding:10px 12px;border-radius:9px;font-size:11.5px;line-height:1.45}.itdna-easy-verdict.ok{border:1px solid #bfe8cf;background:#effaf4;color:#176b45}.itdna-easy-verdict.error{border:1px solid #f1c5c5;background:#fff4f4;color:#9b2d2d}.itdna-easy-verdict.info{border:1px solid #d8e3ef;background:#f7faff;color:#56687f}.itdna-easy-verdict[hidden]{display:none}
     279.itdna-easy-limitations{margin-top:10px;padding:10px 12px;border:1px solid #f0d6a6;border-radius:9px;background:#fffaf0;color:#74541b;font-size:11px;line-height:1.5}.itdna-easy-limitations>strong{display:block;margin-bottom:4px;color:#704b0a!important;font-size:11.5px!important}.itdna-easy-limitations[hidden]{display:none}
     280.itdna-easy-footer{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-top:12px}.itdna-easy-footer small{max-width:980px;color:#7a8798;font-size:10px;line-height:1.45}.itdna-easy-footer .button{flex:0 0 auto}
     281@media(max-width:800px){.itdna-easy-head,.itdna-easy-footer{align-items:flex-start;flex-direction:column}.itdna-easy-steps{grid-template-columns:1fr 1fr}.itdna-easy-compare-head,.itdna-easy-compare-row{grid-template-columns:1.25fr 1fr 1fr}.itdna-easy-footer .button{width:100%}}
     282
     283/* v2.33.19 honest Easy Setup outcome summary */
     284.itdna-easy-outcome-grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:8px;margin:10px 0 12px}.itdna-easy-outcome-grid>div{padding:10px;border:1px solid #e1e8f1;border-radius:9px;background:#fff}.itdna-easy-outcome-grid span{display:block;color:#71809a;font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.035em}.itdna-easy-outcome-grid strong{display:block;margin:5px 0 2px;color:#183b66;font-size:14px;line-height:1.2}.itdna-easy-outcome-grid small{display:block;color:#8a96a8;font-size:9.5px;line-height:1.3}
     285@media(max-width:1050px){.itdna-easy-outcome-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(max-width:650px){.itdna-easy-outcome-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
     286
     287.itdna-easy-result-details{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px}.itdna-easy-result-details>div{padding:10px 12px;border:1px solid #dfe8f3;border-radius:9px;background:#f9fbfe;color:#5d6e84;font-size:10.5px;line-height:1.5}.itdna-easy-result-details strong{display:block;margin-bottom:4px;color:#26486f;font-size:11px}.itdna-easy-result-details[hidden]{display:none}@media(max-width:750px){.itdna-easy-result-details{grid-template-columns:1fr}}
     288
     289
     290/* v2.35.17 — Unified non-Dashboard admin UI
     291 * Dashboard is intentionally excluded. This layer normalizes typography, spacing,
     292 * controls and the visual palette across every other Turbo Cache screen without
     293 * changing any runtime/performance setting, JS hook, form name or module behavior.
     294 */
     295.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]){
     296  --itdna-ui-text:#17233b;
     297  --itdna-ui-body:#52627a;
     298  --itdna-ui-muted:#7c89a0;
     299  --itdna-ui-border:#e3e9f2;
     300  --itdna-ui-border-soft:#edf1f6;
     301  --itdna-ui-surface:#fff;
     302  --itdna-ui-soft:#f7f9fc;
     303  --itdna-ui-blue:#2f80ed;
     304  --itdna-ui-blue-soft:#edf5ff;
     305  --itdna-ui-green:#11653f;
     306  --itdna-ui-green-soft:#edfff7;
     307  --itdna-ui-amber:#8a5a09;
     308  --itdna-ui-amber-soft:#fff7df;
     309  --itdna-ui-red:#9c2828;
     310  --itdna-ui-red-soft:#fff1f1;
     311  color:var(--itdna-ui-body);
     312  font-size:13px!important;
     313  line-height:1.5!important;
     314}
     315.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(button,input,select,textarea,.button){font-family:inherit!important}
     316.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(p,li,td,th,label){line-height:1.5}
     317.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-card,.itdna-auto-type,.itdna-easy-setup,.itdna-v20-engine,.itdna-asset-section,.itdna-auto-choice-dialog){border-color:var(--itdna-ui-border)!important}
     318.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-card-head,.itdna-asset-section-head,.itdna-v20-summary,.itdna-v20-note){border-color:var(--itdna-ui-border-soft)!important}
     319
     320/* One readable type scale for all non-Dashboard screens. */
     321.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-head h2{font-size:16px!important;line-height:1.35!important;font-weight:650!important;color:var(--itdna-ui-text)!important}
     322.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-head p{font-size:12.5px!important;line-height:1.5!important;color:var(--itdna-ui-muted)!important}
     323.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-toggle-row strong,.itdna-field strong,.itdna-field-row strong,.itdna-diagnostic strong,.itdna-manual-check strong,.itdna-detect-card strong,.itdna-plugin-row strong,.itdna-plan-row strong,.itdna-asset-stat-label,.itdna-compat-label){font-size:13.5px!important;line-height:1.4!important;font-weight:650!important;color:var(--itdna-ui-text)!important}
     324.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-toggle-row small,.itdna-field small,.itdna-field-row small,.itdna-diagnostic small,.itdna-manual-check small,.itdna-detect-card small,.itdna-plugin-row small,.itdna-plan-row small,.itdna-compat-status small,.itdna-help,.itdna-info){font-size:12px!important;line-height:1.5!important;color:var(--itdna-ui-muted)!important}
     325.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-kicker,.itdna-asset-kicker,.itdna-plugin-row.head,.itdna-plan-row.head,.itdna-v20-summary span,.itdna-easy-outcome-grid span,.itdna-auto-choice-badge,.itdna-easy-badge){font-size:11px!important;line-height:1.35!important;letter-spacing:.045em!important}
     326.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-risk,.itdna-role,.itdna-value,.itdna-integrity-badge,.itdna-integrity-badge strong,.itdna-compat-badge,.itdna-owner-standby-badge,.itdna-server-badge){font-size:11px!important;line-height:1.3!important}
     327
     328/* Controls use the same dimensions and font everywhere. */
     329.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-top-actions .button,.itdna-actions .button,.itdna-card .button,.itdna-auto-hero-actions .button,.itdna-v20-actions .button,.itdna-inline-help .button,.itdna-owner-inline-actions .button,.itdna-easy-footer .button,.itdna-auto-choice-foot .button){min-height:34px!important;height:auto!important;padding:6px 12px!important;border-radius:7px!important;font-size:13px!important;line-height:1.4!important;font-weight:600!important}
     330.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .button.button-large{min-height:38px!important;padding:7px 14px!important;font-size:13.5px!important}
     331.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-field input[type=text],.itdna-field input[type=url],.itdna-field input[type=password],.itdna-field input[type=number],.itdna-field input[type=email],.itdna-field select,.itdna-field textarea,.itdna-field-row select){min-height:40px!important;padding:8px 10px!important;border:1px solid #cfd8e6!important;border-radius:8px!important;background:#fff!important;color:var(--itdna-ui-text)!important;font-size:13px!important;line-height:1.45!important;box-shadow:none!important}
     332.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-field textarea{min-height:104px!important;font-family:inherit!important;font-size:13px!important}
     333.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(input,select,textarea):focus{border-color:#86b7f3!important;box-shadow:0 0 0 1px #86b7f3!important;outline:0!important}
     334
     335/* Consistent cards, rows and neutral surfaces. */
     336.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card{border-radius:12px!important;box-shadow:0 4px 18px rgba(35,55,90,.045)!important}
     337.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-head{padding:15px 18px!important;background:#fff!important}
     338.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-body{padding:15px 18px 17px!important}
     339.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-toggle-row,.itdna-field-row,.itdna-diagnostic,.itdna-db-row,.itdna-manual-check,.itdna-v20-step){border-color:var(--itdna-ui-border-soft)!important}
     340.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-row{padding:12px 0!important;gap:18px!important}
     341.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-field{margin-bottom:15px!important}
     342.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-engine-note,.itdna-inline-help,.itdna-plan-reasons,.itdna-manual-note,.itdna-step-list,.itdna-owner-situation,.itdna-asset-explainer){font-size:12.5px!important;line-height:1.5!important;color:var(--itdna-ui-body)!important;border-color:#dfe8f3!important;background:#f7faff!important}
     343.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-inline-help strong{font-size:13.5px!important;color:var(--itdna-ui-text)!important}
     344.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-checklist div{font-size:12.5px!important;line-height:1.5!important;color:#365273!important;background:#f6fbff!important;border-color:#e4f1ff!important}
     345
     346/* Auto Optimize / optimizer engine. */
     347.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-auto-hero,.itdna-v20-head,.itdna-pro-preview-head){padding:21px 23px!important;border-radius:14px!important;background:linear-gradient(135deg,#0b1731,#16335f)!important}
     348.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-auto-hero h2,.itdna-v20-head h2,.itdna-pro-preview-head h2){font-size:21px!important;line-height:1.25!important;font-weight:650!important}
     349.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-auto-hero p,.itdna-v20-head p,.itdna-pro-preview-head p){font-size:13px!important;line-height:1.55!important;color:#c6d4ea!important}
     350.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-auto-type{padding:15px 18px!important;border-radius:12px!important}
     351.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-type-main>span{font-size:11px!important;color:var(--itdna-ui-muted)!important}
     352.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-type-main strong{font-size:20px!important;line-height:1.25!important;color:var(--itdna-ui-text)!important}
     353.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-type-main small{font-size:12px!important;color:var(--itdna-ui-muted)!important}
     354.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-chip{font-size:11.5px!important;background:var(--itdna-ui-blue-soft)!important;border-color:#d8e9ff!important;color:#275486!important}
     355.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-detect-card{padding:11px 12px!important;border-radius:9px!important;background:#fbfcfe!important;border-color:var(--itdna-ui-border)!important}
     356.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-detect-card.ok{background:#f5fffa!important;border-color:#d8f2e6!important}
     357.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-plugin-row,.itdna-plan-row){font-size:12.5px!important;padding:11px 13px!important;border-color:var(--itdna-ui-border-soft)!important}
     358.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-plugin-row.head,.itdna-plan-row.head){background:var(--itdna-ui-soft)!important;color:#6f7e95!important;font-weight:800!important}
     359.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-role{background:#eef3f8!important;color:#4f6078!important}
     360.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-value{background:#eef7ff!important;color:#2a5d92!important;padding:4px 8px!important}
     361.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-infra-strip span{font-size:12px!important;color:#607089!important;border-color:var(--itdna-ui-border)!important;background:var(--itdna-ui-soft)!important}
     362.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-v20-summary span{color:var(--itdna-ui-muted)!important}
     363.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-v20-summary strong{font-size:14.5px!important;color:var(--itdna-ui-text)!important}
     364.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-v20-progress small{font-size:12px!important;color:var(--itdna-ui-muted)!important}
     365.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-v20-step strong{font-size:13.5px!important;color:var(--itdna-ui-text)!important}
     366.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-v20-step small{font-size:12px!important;color:var(--itdna-ui-muted)!important}
     367.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-v20-results>div{font-size:12.5px!important;background:var(--itdna-ui-soft)!important;border-color:var(--itdna-ui-border)!important}
     368.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-v20-note{font-size:12px!important;color:#63728a!important;background:#f8fbff!important}
     369
     370/* Asset / compatibility / ownership reports. */
     371.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-asset-section-head h3{font-size:14.5px!important;color:var(--itdna-ui-text)!important}
     372.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-asset-stat{min-height:82px!important;border-color:var(--itdna-ui-border)!important;border-radius:9px!important;background:#fbfdff!important}
     373.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-asset-stat-value{font-size:18px!important;color:#17345e!important}
     374.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-asset-stat small{font-size:11.5px!important;line-height:1.4!important;color:var(--itdna-ui-muted)!important}
     375.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-asset-summary span,.itdna-compat-label){font-size:12px!important;color:#51637c!important}
     376.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-asset-summary strong{font-size:16px!important}
     377.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-compat-status{border-color:var(--itdna-ui-border)!important;background:#fbfdff!important}
     378.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-owner-inline,.itdna-owner-situation){font-size:12.5px!important;line-height:1.5!important;border-radius:9px!important}
     379.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-owner-inline strong{font-size:13px!important;color:var(--itdna-ui-text)!important}
     380.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-owner-inline-actions small{font-size:12px!important;line-height:1.45!important;color:var(--itdna-ui-muted)!important}
     381.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-owner-situation>strong{font-size:13px!important}
     382
     383/* Easy Setup and choice modal use the same typography as the rest when shown outside Dashboard. */
     384.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-easy-head h2{font-size:19px!important;color:var(--itdna-ui-text)!important}
     385.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-easy-head p{font-size:12.5px!important;color:#617089!important}
     386.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-easy-status>strong{font-size:13px!important}
     387.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-easy-status>span{font-size:11px!important}
     388.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-easy-status>p{font-size:12px!important}
     389.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-easy-steps span{font-size:11.5px!important}
     390.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-easy-compare-head,.itdna-easy-compare-row){font-size:12px!important}
     391.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-easy-compare-row>strong{font-size:13px!important}
     392.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-easy-verdict,.itdna-easy-limitations,.itdna-easy-result-details>div){font-size:12px!important;line-height:1.5!important}
     393.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-easy-outcome-grid strong{font-size:14.5px!important}
     394.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-easy-outcome-grid small{font-size:11.5px!important;color:var(--itdna-ui-muted)!important}
     395.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-auto-choice-head h2{font-size:20px!important;color:var(--itdna-ui-text)!important}
     396.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-auto-choice-head p{font-size:13px!important;color:#66758a!important}
     397.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-auto-choice-card>strong{font-size:16px!important;color:var(--itdna-ui-text)!important}
     398.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-auto-choice-card>p{font-size:12.5px!important;color:var(--itdna-ui-body)!important}
     399.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-auto-choice-facts{font-size:12px!important;color:#40536a!important}
     400.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-auto-choice-warning{font-size:12px!important}
     401.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-auto-choice-card em,.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-auto-choice-foot small{font-size:11.5px!important;color:var(--itdna-ui-muted)!important}
     402
     403/* State colors are limited to one shared green / amber / red family. */
     404.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-notice.success{background:var(--itdna-ui-green-soft)!important;border-color:#b6efd6!important;color:var(--itdna-ui-green)!important}
     405.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-notice.error{background:var(--itdna-ui-red-soft)!important;border-color:#ffc9c9!important;color:var(--itdna-ui-red)!important}
     406.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-server-recommended_on,.itdna-compat-badge.is-active,.itdna-integrity-badge.is-pass){background:#effbf5!important;border-color:#b9ead5!important;color:#177451!important}
     407.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-server-background_only,.itdna-server-standby,.itdna-owner-standby-badge){background:var(--itdna-ui-amber-soft)!important;border-color:#f2d08a!important;color:var(--itdna-ui-amber)!important}
     408.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-server-adaptive_off,.itdna-server-default_off,.itdna-compat-badge.is-muted,.itdna-integrity-badge.is-pending){background:#f5f7fa!important;border-color:#dfe5ed!important;color:#66758a!important}
     409.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-server-conditional,.itdna-server-optional,.itdna-compat-badge.is-owner){background:#f1f7ff!important;border-color:#c8ddf7!important;color:#255b9b!important}
     410.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-integrity-badge.is-fail){background:var(--itdna-ui-red-soft)!important;border-color:#ffcaca!important;color:#a12f2f!important}
     411.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-server-advisory{font-size:12.5px!important;line-height:1.5!important}
     412
     413/* Mobile keeps the same type scale; only layout changes. */
     414@media(max-width:782px){
     415  .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-head{padding:14px 15px!important}
     416  .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-body{padding:14px 15px 16px!important}
     417  .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-auto-hero,.itdna-v20-head,.itdna-pro-preview-head){padding:18px!important}
     418}
     419
     420/* v2.35.18 — external cache ownership is a coexistence state, not a false error. */
     421.itdna-notice.info{background:#eef6ff;border-color:#c8ddff;color:#24538a}
     422.itdna-notice.warning{background:#fff8e8;border-color:#f3d79a;color:#7a5511}
     423.itdna-external-control{padding:12px 14px;border:1px solid #d8e5f5;border-radius:10px;background:#f7fbff}
     424.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-notice.info{background:#eef6ff!important;border-color:#c8ddff!important;color:#24538a!important}
     425.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-notice.warning{background:#fff8e8!important;border-color:#f3d79a!important;color:#7a5511!important}
     426
     427/* v2.35.19 — shell-stable partial navigation + honest real-speed evidence. */
     428.itdna-main{position:relative}
     429.itdna-main.itdna-nav-loading{cursor:progress}
     430.itdna-main.itdna-nav-loading::before{content:"";position:absolute;left:0;right:0;top:0;height:3px;z-index:70;background:linear-gradient(90deg,#2f80ed 0%,#62a8ff 45%,#2f80ed 100%);background-size:180% 100%;animation:itdnaNavProgress .8s linear infinite;border-radius:0 0 3px 3px;pointer-events:none}
     431.itdna-main.itdna-nav-loading .itdna-top-actions{pointer-events:none}
     432@keyframes itdnaNavProgress{0%{background-position:100% 0}100%{background-position:-80% 0}}
     433@media (prefers-reduced-motion:reduce){.itdna-main.itdna-nav-loading::before{animation:none}}
     434
     435.itdna-real-speed-note{margin:12px 0 14px;padding:12px 14px;border:1px solid #c9def8;border-radius:10px;background:#f4f9ff;color:#2c507a;font-size:12.5px;line-height:1.55}
     436.itdna-real-speed-note strong{color:#173c68}
     437.itdna-browser-proof{margin:14px 0;border:1px solid #dfe7f1;border-radius:12px;background:#fff;overflow:hidden}
     438.itdna-browser-proof-head{padding:13px 15px;border-bottom:1px solid #edf1f6;display:flex;gap:8px;flex-direction:column}
     439.itdna-browser-proof-head strong{font-size:14px;color:#17233b}
     440.itdna-browser-proof-head span{font-size:12px;color:#71809a}
     441.itdna-browser-proof-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0}
     442.itdna-browser-proof-card{padding:14px 15px;min-width:0;border-right:1px solid #edf1f6}
     443.itdna-browser-proof-card:last-child{border-right:0}
     444.itdna-browser-proof-card>span{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.04em;font-weight:750;color:#73839c}
     445.itdna-browser-proof-card>strong{display:block;margin:5px 0 4px;font-size:18px;color:#1a2942}
     446.itdna-browser-proof-card>small{display:block;font-size:11.5px;line-height:1.45;color:#75839a}
     447.itdna-browser-proof-card.improved{background:#f5fff9}
     448.itdna-browser-proof-card.improved>strong{color:#147348}
     449.itdna-browser-proof-card.regressed{background:#fff6f6}
     450.itdna-browser-proof-card.regressed>strong{color:#a12f2f}
     451.itdna-browser-proof-card.neutral{background:#fffbf2}
     452.itdna-browser-proof-card.neutral>strong{color:#7b5a12}
     453@media(max-width:782px){.itdna-browser-proof-grid{grid-template-columns:1fr}.itdna-browser-proof-card{border-right:0;border-bottom:1px solid #edf1f6}.itdna-browser-proof-card:last-child{border-bottom:0}}
     454.itdna-side-status small{display:block;margin:4px 0 0 14px;color:#7890b5;font-size:10.5px;line-height:1.35}
     455\n\n/* v2.35.20 — Compact contextual admin density.
     456 * Dashboard remains intentionally untouched. The adaptive recommendation now
     457 * belongs visually to its own option row, while cards/forms/notices use space
     458 * according to information importance rather than one oversized default.
     459 */
     460.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]){
     461  --itdna-density-title:13.5px;
     462  --itdna-density-body:11.75px;
     463  --itdna-density-meta:10.5px;
     464}
     465.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-top{margin-bottom:13px!important}
     466.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-top h1{font-size:25px!important;line-height:1.2!important;letter-spacing:-.015em!important}
     467.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-top p{margin-top:4px!important;font-size:12px!important;line-height:1.4!important}
     468
     469/* Cards: compact shell, still roomy enough to scan. */
     470.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card{margin-bottom:12px!important;border-radius:11px!important}
     471.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-head{padding:12px 16px 11px!important}
     472.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-head h2{font-size:15px!important;line-height:1.3!important;font-weight:650!important}
     473.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-head p{margin:3px 0 0!important;font-size:11.75px!important;line-height:1.4!important}
     474.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-body{padding:8px 16px 11px!important}
     475
     476/* Each option is one visual unit: name + chips, explanation, policy, switch. */
     477.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-row{align-items:center!important;gap:14px!important;padding:10px 0!important}
     478.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-row>.itdna-toggle-copy{display:flex!important;flex:1 1 auto!important;min-width:0!important;flex-direction:column!important;gap:3px!important;padding-right:8px!important}
     479.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-titleline{display:flex!important;flex-direction:row!important;align-items:center!important;flex-wrap:wrap!important;gap:5px!important;min-width:0!important}
     480.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-titleline>strong{display:inline!important;font-size:var(--itdna-density-title)!important;line-height:1.28!important;font-weight:650!important;margin:0 2px 0 0!important;color:var(--itdna-ui-text)!important}
     481.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-desc{display:block!important;margin:0!important;max-width:980px!important;font-size:var(--itdna-density-body)!important;line-height:1.4!important;color:#74839a!important}
     482.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-risk,.itdna-server-badge,.itdna-owner-standby-badge){display:inline-flex!important;align-items:center!important;width:auto!important;margin:0!important;padding:2px 6px!important;border-radius:999px!important;font-size:9.75px!important;line-height:1.25!important;font-weight:750!important;letter-spacing:.015em!important;white-space:nowrap!important}
     483
     484/* Replaces the old detached full-width server advisory banner. */
     485.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-policy{display:flex!important;flex-direction:row!important;align-items:baseline!important;gap:4px!important;width:auto!important;max-width:980px!important;margin:1px 0 0!important;padding:0 0 0 7px!important;border:0!important;border-left:2px solid #cbd5e1!important;border-radius:0!important;background:transparent!important;font-size:10.75px!important;line-height:1.38!important;color:#64748b!important}
     486.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-policy b{flex:0 0 auto!important;font-size:10.75px!important;font-weight:700!important;color:#475569!important}
     487.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-policy>span{display:inline!important;min-width:0!important}
     488.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-policy-recommended_on{border-left-color:#86d6aa!important;color:#397054!important}
     489.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-policy-recommended_on b{color:#17623f!important}
     490.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-policy-conditional{border-left-color:#8bc9ec!important;color:#406d88!important}
     491.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-policy-standby,.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-policy-background_only{border-left-color:#e7c66d!important;color:#765d22!important}
     492.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-policy-adaptive_off,.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-policy-default_off{border-left-color:#cbd5e1!important;color:#64748b!important}
     493
     494/* Switch stays compact and aligned with its own option. */
     495.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-switch{flex:0 0 40px!important;width:40px!important;min-width:40px!important;height:22px!important;margin:0!important}
     496
     497/* Forms and free-text fields: consistent but not oversized. */
     498.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-field{margin-bottom:11px!important}
     499.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-field strong,.itdna-field-row strong){font-size:13px!important;line-height:1.35!important;font-weight:650!important}
     500.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-field small,.itdna-field-row small){margin-top:2px!important;font-size:11.5px!important;line-height:1.4!important}
     501.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-field input[type=text],.itdna-field input[type=url],.itdna-field input[type=password],.itdna-field input[type=number],.itdna-field input[type=email],.itdna-field select,.itdna-field-row select){min-height:36px!important;padding:6px 9px!important;border-radius:7px!important;font-size:12.5px!important}
     502.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-field textarea{min-height:86px!important;padding:7px 9px!important;font-size:12px!important;line-height:1.4!important}
     503
     504/* Notices/help should inform, not dominate the screen. */
     505.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-notice{margin:0 0 10px!important;padding:8px 11px!important;border-radius:8px!important;font-size:11.75px!important;line-height:1.42!important}
     506.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-engine-note,.itdna-inline-help,.itdna-plan-reasons,.itdna-manual-note,.itdna-step-list,.itdna-owner-situation,.itdna-asset-explainer){padding:8px 10px!important;font-size:11.75px!important;line-height:1.42!important;border-radius:8px!important}
     507.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-info{margin:7px 0!important;font-size:11.5px!important;line-height:1.4!important}
     508.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-owner-inline{margin:6px 0 9px!important;padding:8px 10px!important;border-radius:8px!important;font-size:11.5px!important;line-height:1.4!important}
     509.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-owner-inline-actions{margin-top:6px!important;gap:7px!important}
     510
     511/* Tables / diagnostics / metric tiles use the same compact rhythm. */
     512.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-diagnostic,.itdna-db-row,.itdna-manual-check,.itdna-v20-step){padding-top:8px!important;padding-bottom:8px!important}
     513.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) :where(.itdna-plugin-row,.itdna-plan-row){padding:8px 11px!important;font-size:11.75px!important}
     514.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-asset-stat{min-height:68px!important;padding-top:10px!important;padding-bottom:10px!important}
     515.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-checklist{gap:7px!important}
     516.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-checklist div{padding:8px 10px!important;font-size:11.75px!important;line-height:1.4!important}
     517
     518@media(max-width:782px){
     519  .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-head{padding:11px 13px 10px!important}
     520  .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-card-body{padding:7px 13px 10px!important}
     521  .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-row{gap:10px!important;padding:9px 0!important}
     522  .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-policy{display:block!important;padding-left:6px!important}
     523  .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-toggle-policy b{display:inline!important;margin-right:3px!important}
     524}
     525
     526/* v2.35.22 — Compact Adaptive Server Profiler. The markup always used
     527   itdna-mini-grid; this supplies the missing layout so capability values do not
     528   stack into a very tall single column. Scoped to Auto Optimize/server profiler. */
     529.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card{margin-top:12px!important}
     530.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-card-head{padding:10px 14px!important}
     531.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-card-head h2{font-size:15px!important;line-height:1.25!important;margin:0!important}
     532.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-card-head p{font-size:11.25px!important;line-height:1.38!important;margin:3px 0 0!important;max-width:1050px}
     533.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-card-body{padding:11px 14px 12px!important}
     534.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-mini-grid{display:grid!important;grid-template-columns:repeat(3,minmax(0,1fr))!important;gap:7px!important;margin:0!important}
     535.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-mini-grid>div{min-width:0;padding:7px 9px!important;border:1px solid #e2e8f0;border-radius:7px;background:#fbfdff;display:flex!important;flex-direction:column!important;gap:2px!important}
     536.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-mini-grid>div>span{font-size:10.25px!important;line-height:1.2!important;font-weight:650!important;color:#7a8799!important;margin:0!important;text-transform:none!important;letter-spacing:0!important}
     537.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-mini-grid>div>strong{font-size:12.25px!important;line-height:1.3!important;font-weight:700!important;color:#42536c!important;margin:0!important;overflow-wrap:anywhere}
     538.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-server-reasons{margin:8px 0 0!important;padding:0!important;background:#f8fbff!important;border:1px solid #e2eaf4!important;border-radius:7px!important;overflow:hidden}
     539.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-server-reasons>summary{cursor:pointer;list-style:none;padding:7px 9px!important;font-size:11px!important;line-height:1.3!important;color:#445872!important;display:flex;align-items:center;gap:6px}
     540.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-server-reasons>summary::-webkit-details-marker{display:none}
     541.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-server-reasons>summary:before{content:'›';font-size:16px;line-height:1;transition:transform .15s ease;color:#64748b}
     542.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-server-reasons[open]>summary:before{transform:rotate(90deg)}
     543.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-server-reasons>summary span{font-size:10px;font-weight:600;color:#8795a8}
     544.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-server-reason-list{padding:0 9px 7px 26px!important}
     545.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-server-reason-list>div{font-size:10.75px!important;line-height:1.38!important;margin:3px 0!important;color:#607087!important}
     546.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-actions{margin-top:8px!important}
     547.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-actions .button{min-height:30px!important;height:30px!important;padding:0 10px!important;font-size:11.5px!important}
     548.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-help{margin:7px 0 0!important;padding:0!important;font-size:10.5px!important;line-height:1.35!important;color:#8190a3!important;background:transparent!important;border:0!important}
     549.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-info{margin:8px 0 0!important;padding:7px 9px!important;font-size:10.75px!important;line-height:1.35!important}
     550@media(max-width:1100px){.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-mini-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important}}
     551@media(max-width:640px){.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-mini-grid{grid-template-columns:1fr!important}.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-card-head,.itdna-main[data-itdna-tab="autooptimize"] .itdna-server-profile-card .itdna-card-body{padding-left:10px!important;padding-right:10px!important}}
     552
     553
     554/* v2.35.25 — category-wise single-open accordions for non-dashboard pages */
     555.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-card{overflow:hidden}
     556.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-head{display:grid!important;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:12px;cursor:pointer;user-select:none;transition:background-color .16s ease,border-color .16s ease}
     557.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-head h2,.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-head p{grid-column:1}
     558.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-head:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}
     559.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-indicator{grid-column:2;grid-row:1 / span 2;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:999px;border:1px solid #d7e3f4;background:#f7fbff;color:#284d8f;font-size:20px;line-height:1;font-weight:700;box-shadow:inset 0 1px 0 rgba(255,255,255,.8)}
     560.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-card.itdna-acc-open>.itdna-card-head{background:linear-gradient(180deg,#f8fbff 0%,#ffffff 100%)!important;border-bottom-color:#e2ebf7!important}
     561.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-card.itdna-acc-collapsed>.itdna-card-head{border-bottom:0!important}
     562.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-card.itdna-acc-collapsed>.itdna-card-body{display:none!important}
     563.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-card.itdna-acc-open{box-shadow:0 8px 24px rgba(34,56,96,.08)!important;border-color:#d8e5f7!important}
     564.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-card.itdna-acc-collapsed{box-shadow:0 2px 12px rgba(35,55,90,.04)!important}
     565@media (max-width:782px){
     566  .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-accordion-indicator{width:26px;height:26px;font-size:18px}
     567}
     568
     569
     570/* v2.35.27 — true nested category view: all headers visible, one section open at a time. */
     571.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-category-host>.itdna-card-body{display:block!important;padding:10px 12px 12px!important}
     572.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-category-host>.itdna-card-head{background:#fff!important;border-bottom:1px solid #edf1f6!important;cursor:default!important}
     573.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-category-stack{display:grid;gap:7px}
     574.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category{border:1px solid #dfe7f2;border-radius:10px;background:#fff;overflow:hidden;box-shadow:0 2px 8px rgba(31,48,78,.035)}
     575.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-trigger{appearance:none;-webkit-appearance:none;width:100%;border:0;margin:0;padding:10px 12px;background:#f8fafc;color:#17233b;display:grid;grid-template-columns:minmax(0,1fr) 28px;gap:12px;align-items:center;text-align:left;cursor:pointer;font:inherit;transition:background-color .15s ease,box-shadow .15s ease}
     576.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-trigger:hover{background:#f2f7ff}
     577.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-trigger:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}
     578.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-copy{min-width:0;display:block}
     579.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-copy>strong{display:block;font-size:13.5px;line-height:1.25;font-weight:700;color:#17233b}
     580.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-copy>small{display:block;margin-top:2px;font-size:11px;line-height:1.3;color:#77869d;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
     581.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-icon{width:26px;height:26px;border:1px solid #d5e2f4;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;background:#fff;color:#31588f;font-size:18px;font-weight:700;line-height:1}
     582.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-body{padding:5px 13px 9px;background:#fff;border-top:1px solid #e7edf5}
     583.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-body[hidden]{display:none!important}
     584.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category.itdna-category-open{border-color:#bdd3f3;box-shadow:0 7px 20px rgba(42,74,120,.075)}
     585.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category.itdna-category-open>.itdna-option-category-trigger{background:#f2f7ff}
     586.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-category-host .itdna-toggle-row{padding:9px 0!important}
     587.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-category-host .itdna-field{margin-bottom:10px!important}
     588.itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-category-host .itdna-info{margin:8px 0!important}
     589@media(max-width:782px){
     590 .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-category-host>.itdna-card-body{padding:8px!important}
     591 .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-trigger{padding:10px;grid-template-columns:minmax(0,1fr) 26px}
     592 .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-copy>small{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
     593 .itdna-main[data-itdna-tab]:not([data-itdna-tab="dashboard"]) .itdna-option-category-body{padding:4px 10px 8px}
     594}
     595
     596/* v2.35.30 — Easy Auto Setup primary action sits directly after live progress/status. */
     597.itdna-easy-primary-action{display:flex;align-items:center;justify-content:flex-start;margin:10px 0 12px}
     598.itdna-easy-primary-action .button{min-height:36px;padding:4px 16px;font-weight:650}
     599.itdna-easy-primary-action .button[hidden]{display:none!important}
     600@media(max-width:782px){.itdna-easy-primary-action .button{width:100%;justify-content:center}}
     601
     602
     603/* v2.35.33 — Cloudflare connection/status unified card */
     604.itdna-main[data-itdna-tab="cloudflare"] .itdna-cf-status-block{padding:0 0 10px;margin:0 0 10px;border-bottom:1px solid #e8eef6}
     605.itdna-main[data-itdna-tab="cloudflare"] .itdna-cf-status-block .itdna-notice,.itdna-main[data-itdna-tab="cloudflare"] .itdna-cf-status-block .itdna-engine-note{margin-bottom:8px!important}
     606.itdna-main[data-itdna-tab="cloudflare"] .itdna-cf-section-title{display:flex;flex-direction:column;gap:2px;padding:2px 0 8px}
     607.itdna-main[data-itdna-tab="cloudflare"] .itdna-cf-section-title>strong{font-size:13.5px;color:#17233b}
     608.itdna-main[data-itdna-tab="cloudflare"] .itdna-cf-section-title>small{font-size:11.5px;line-height:1.4;color:#7c89a0}
     609
     610
     611/* v2.35.34 — immediate action feedback for slow shared-host admin requests */
     612.itdna-global-busy{position:fixed;top:44px;right:20px;z-index:100500;display:flex;align-items:center;gap:9px;max-width:min(390px,calc(100vw - 32px));padding:10px 13px;border:1px solid #d6e3f5;border-radius:10px;background:#fff;color:#1d3557;box-shadow:0 10px 30px rgba(20,43,80,.18);font:600 12.5px/1.35 Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;opacity:0;transform:translateY(-8px);pointer-events:none;transition:opacity .14s ease,transform .14s ease}
     613.itdna-global-busy.show{opacity:1;transform:translateY(0)}
     614.itdna-busy-spinner{width:15px;height:15px;flex:0 0 15px;border:2px solid #cfe0f6;border-top-color:#2f6feb;border-radius:50%;animation:itdnaBusySpin .7s linear infinite}
     615.itdna-is-working{pointer-events:none!important;opacity:.78!important;cursor:progress!important}
     616@keyframes itdnaBusySpin{to{transform:rotate(360deg)}}
     617@media(max-width:782px){.itdna-global-busy{top:52px;right:10px;left:10px;max-width:none}}
     618@media(prefers-reduced-motion:reduce){.itdna-busy-spinner{animation:none}.itdna-global-busy{transition:none}}
     619
     620/* v2.35.35 — make homepage-origin vs browser/PageSpeed scope explicit */
     621.itdna-measurement-scope{display:flex;gap:8px;align-items:flex-start;padding:10px 12px;margin:8px 0 12px;border:1px solid #cfe0f7;border-radius:9px;background:#f6faff;color:#35506f;font-size:12px;line-height:1.45}.itdna-measurement-scope strong{color:#17365d;white-space:nowrap}.itdna-measurement-scope span{min-width:0}@media(max-width:782px){.itdna-measurement-scope{display:block}.itdna-measurement-scope strong{display:block;margin-bottom:3px;white-space:normal}}
     622
     623/* v2.35.39 — Performance Doctor summary merged into the engine card. */
     624.itdna-main[data-itdna-tab="doctor"] .itdna-doctor-summary-grid{margin:0 0 12px!important;grid-template-columns:repeat(4,minmax(0,1fr))!important}
     625.itdna-main[data-itdna-tab="doctor"] .itdna-doctor-summary-grid .itdna-metric{box-shadow:none!important;background:#f8fafc!important;border-color:#e4eaf2!important;padding:13px 14px!important}
     626@media(max-width:1000px){.itdna-main[data-itdna-tab="doctor"] .itdna-doctor-summary-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important}}
     627@media(max-width:640px){.itdna-main[data-itdna-tab="doctor"] .itdna-doctor-summary-grid{grid-template-columns:1fr!important}}
     628
     629
     630/* v2.35.41 — Cache Analytics unified default-open card */
     631.itdna-main[data-itdna-tab="analytics"] .itdna-in-card-metrics{margin:0 0 14px!important}
     632.itdna-main[data-itdna-tab="analytics"] .itdna-in-card-metrics .itdna-metric{box-shadow:none!important;background:#f8fbff!important}
     633
     634/* v1.3.51: top-of-dashboard scheduler controls and measured host load. */
     635.itdna-speed-console{background:#fff;border:1px solid #dbe5f2;border-radius:14px;box-shadow:0 5px 18px rgba(28,47,83,.06);padding:17px 20px 13px;margin:-2px 0 20px}
     636.itdna-speed-heading{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:14px}
     637.itdna-speed-heading h2{margin:0 0 5px;font-size:17px;line-height:1.25;color:#182746}
     638.itdna-speed-heading p{margin:0;color:#6d7e98;font-size:12px;line-height:1.45}
     639.itdna-speed-chip{background:#edfdf6;border:1px solid #bcebd4;color:#197647;border-radius:99px;font-size:11px;font-weight:750;padding:5px 11px;white-space:nowrap}
     640.itdna-speed-form{display:grid;grid-template-columns:minmax(150px,1fr) minmax(170px,1fr) minmax(220px,1.25fr) auto;gap:12px;align-items:end;margin:0 0 13px}
     641.itdna-speed-field{display:flex;flex-direction:column;gap:5px;font-size:13px;min-width:0}
     642.itdna-speed-field strong{color:#253958;font-size:13px}
     643.itdna-speed-field span{color:#7a889e;min-height:16px;font-size:11px}
     644.itdna-speed-field select{width:100%;max-width:none;min-height:38px;border:1px solid #cfdbeb;border-radius:8px;color:#1e2e48;background:#fafdff;padding:5px 10px;font-weight:650}
     645.itdna-speed-health{min-height:37px;display:flex;flex-direction:column;justify-content:center;gap:2px;padding:7px 10px;border-radius:9px;border:1px solid #b9e8cf;background:#edfbf3;color:#176342;box-sizing:border-box}
     646.itdna-speed-health strong{font-size:12px;line-height:1.3}
     647.itdna-speed-health small{font-size:10px;line-height:1.3;opacity:.86}
     648.itdna-speed-health.is-warm{background:#fff9e9;border-color:#f1d8a1;color:#9e5a0a}
     649.itdna-speed-health.is-hot{background:#fff0f0;border-color:#ffc1c1;color:#a82432}
     650.itdna-speed-health.is-ice{background:#edf7ff;border-color:#c5dfff;color:#296394}
     651.itdna-speed-save.button.button-primary{height:38px!important;min-height:38px!important;margin:0!important;padding:5px 15px!important;white-space:nowrap;font-weight:700!important}
     652.itdna-speed-load{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;border-top:1px solid #e8eef7;padding-top:12px}
     653.itdna-speed-load>div{display:flex;flex-direction:column;min-width:0;gap:4px;padding:10px 12px;background:#f7f9fe;border:1px solid #ebf0f8;border-radius:9px}
     654.itdna-speed-load span{font-size:11px;font-weight:650;color:#637691}
     655.itdna-speed-load strong{font-size:18px;color:#193656;line-height:1.2}
     656.itdna-speed-load small{font-size:10.5px;color:#7b879a;overflow-wrap:anywhere;line-height:1.35}
     657.itdna-speed-footnote{color:#7b879a;font-size:11px!important;line-height:1.5;margin:11px 0 0!important}
     658@media(max-width:1100px){.itdna-speed-form{grid-template-columns:repeat(2,minmax(0,1fr))}.itdna-speed-health{min-height:42px}}
     659@media(max-width:600px){.itdna-speed-console{padding:14px 12px}.itdna-speed-form,.itdna-speed-load{grid-template-columns:1fr}.itdna-speed-field span{min-height:0}.itdna-speed-save.button.button-primary{width:100%}}
     660
     661/* v1.3.52 — primary Smart Speed Slider; manual controls in expandable panel. */
     662.itdna-speed-form.itdna-smart-form{display:grid;grid-template-columns:minmax(0,1fr) minmax(210px,270px);gap:14px;align-items:stretch;margin:0 0 15px}
     663.itdna-smart-main{min-width:0;padding:15px 17px;border:1px solid #dfe8f5;border-radius:12px;background:#f9fbff}
     664.itdna-smart-label{display:flex;justify-content:space-between;align-items:center;gap:14px}
     665.itdna-smart-label label{display:flex;flex-direction:column;gap:5px}
     666.itdna-smart-label strong{font-size:15px;color:#1f3457}
     667.itdna-smart-label small{font-size:11px;color:#697c98}
     668.itdna-smart-label output{font-size:25px;font-weight:800;color:#1955d5;white-space:nowrap}
     669.itdna-smart-main input[type=range]{display:block;width:100%;max-width:none;margin:19px 0 9px;accent-color:#345ce4;cursor:pointer}
     670.itdna-smart-endpoints{display:flex;align-items:center;justify-content:space-between;gap:7px;font-size:10.5px;color:#6c7b92;margin-bottom:13px}
     671.itdna-speed-radio{display:flex;align-items:center;gap:7px;font-size:12px;font-weight:600;color:#344b68}
     672.itdna-speed-radio input{margin:0!important}
     673.itdna-smart-sidebar{display:flex;flex-direction:column;gap:10px;justify-content:space-between}
     674.itdna-smart-sidebar .itdna-speed-health{flex:1;padding:12px 13px}
     675.itdna-smart-sidebar .itdna-speed-health strong{font-size:13px}
     676.itdna-smart-sidebar .itdna-speed-health small{font-size:11px}
     677.itdna-effective-stats{display:flex;flex-wrap:wrap;justify-content:space-between;gap:6px;padding:8px 10px;border-radius:8px;background:#f4f7fc;border:1px solid #e5ebf5;color:#435978;font-size:11px}
     678.itdna-effective-stats span{white-space:nowrap}
     679.itdna-effective-stats strong{color:#1b3568}
     680.itdna-smart-sidebar .itdna-speed-save{width:100%;justify-content:center}
     681.itdna-speed-advanced{grid-column:1/-1;border:1px solid #e6edf5;border-radius:10px;padding:10px 14px;background:#fcfdff}
     682.itdna-speed-advanced summary{font-size:12px;font-weight:700;color:#435a76;cursor:pointer}
     683.itdna-speed-advanced p{font-size:11px;color:#6f7e97;line-height:1.45;margin:9px 0}
     684.itdna-speed-advanced-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:11px}
     685@media(max-width:850px){.itdna-speed-form.itdna-smart-form{grid-template-columns:1fr}.itdna-speed-advanced{grid-column:1}.itdna-smart-sidebar{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center}.itdna-smart-sidebar .itdna-speed-save{grid-column:1/-1}.itdna-smart-sidebar .itdna-effective-stats{min-width:190px}}
     686@media(max-width:600px){.itdna-smart-main{padding:12px}.itdna-smart-endpoints{font-size:9px}.itdna-smart-sidebar{display:flex}.itdna-speed-advanced-fields{grid-template-columns:1fr}}
     687
     688/* v1.3.53 — hosting guard, force-lock warning, real protection status */
     689.itdna-host-power-save-form{display:none}
     690.itdna-hosting-guard{grid-column:1/-1;background:#f7faff;border:1px solid #d4e2f5;border-radius:11px;padding:14px 16px;display:grid;gap:10px}
     691.itdna-hosting-guard h3{margin:0;font-size:15px;color:#1c3654}
     692.itdna-hosting-guard p{margin:0;font-size:12px;line-height:1.5}
     693.itdna-hosting-select{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
     694.itdna-hosting-select label{display:flex;flex-direction:column;gap:4px;max-width:560px}
     695.itdna-hosting-select strong{font-size:12px}
     696.itdna-hosting-select small{font-size:11px;color:#5a6981}
     697.itdna-hosting-select select{max-width:280px;min-height:37px}
     698.itdna-host-warning{color:#8a4f03;background:#fff3d8;border:1px solid #f5cb76;border-radius:8px;padding:9px 11px}
     699.itdna-host-warning.is-danger,.itdna-host-emergency{background:#fff0ef!important;border:1px solid #f4a6a6!important;color:#9c1924!important;padding:9px 11px;border-radius:8px}
     700.itdna-host-explain{color:#697e9a;font-size:11px;line-height:1.4}
     701.itdna-host-confirm{font-size:11px;color:#854321}
     702.itdna-host-status{padding:10px 12px;border-radius:9px;background:#f3f8ff;border:1px solid #dce7f5;font-size:12px;margin-bottom:10px}
     703.itdna-host-log{margin-top:10px;border-top:1px solid #e5e9ef;padding-top:8px;font-size:11px}
     704.itdna-host-log summary{cursor:pointer;font-weight:650}
     705.itdna-host-log li{margin:4px 0}
     706.itdna-host-reset{margin:9px 0}
     707
     708
     709/* v1.3.54: clear, accessible ON/OFF for adaptive background hosting speed. */
     710.itdna-host-top{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px}
     711.itdna-host-top h3{margin:0 0 4px}
     712.itdna-host-toggle-wrap{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
     713.itdna-host-power-state{border:1px solid #86d2ae;background:#e9fcf0;color:#08633f;padding:6px 12px;border-radius:99px;font-size:12px;font-weight:800;letter-spacing:.02em}
     714.itdna-host-power-state.is-off{border-color:#bbc6d3;background:#eef1f5;color:#526170}
     715.itdna-host-power-switch{border:1px solid #bfd2df;background:white;border-radius:99px;padding:6px 13px 6px 7px;display:inline-flex;align-items:center;gap:9px;min-height:41px;font-size:12px;font-weight:800;cursor:pointer;color:#2b4158;transition:box-shadow .15s ease,border-color .15s ease}
     716.itdna-host-power-switch:hover{box-shadow:0 3px 13px rgba(25,58,76,.14)}
     717.itdna-host-power-switch:focus-visible{outline:3px solid #2271b1;outline-offset:3px}
     718.itdna-host-power-switch:disabled{opacity:.65;cursor:wait}
     719.itdna-host-power-track{display:inline-flex;align-items:center;width:46px;height:25px;padding:3px;box-sizing:border-box;border-radius:99px;background:#aab6c3;transition:background .17s ease}
     720.itdna-host-power-knob{display:block;width:19px;height:19px;background:#fff;border-radius:50%;box-shadow:0 1px 3px rgba(10,30,50,.2);transform:translateX(0);transition:transform .17s ease}
     721.itdna-host-power-switch.is-on .itdna-host-power-track{background:#139b61}
     722.itdna-host-power-switch.is-on .itdna-host-power-knob{transform:translateX(21px)}
     723.itdna-host-toggle-help{color:#506881!important;font-size:11px!important;line-height:1.45}
     724.itdna-hosting-guard.itdna-host-off{background:#f6f8fa;border-color:#d9e0e8}
     725.itdna-hosting-guard.itdna-host-off .itdna-hosting-select,.itdna-hosting-guard.itdna-host-off .itdna-host-lock,.itdna-hosting-guard.itdna-host-off .itdna-host-confirm{opacity:.55}
     726@media(max-width:650px){.itdna-host-toggle-wrap{justify-content:flex-start;width:100%}.itdna-host-power-switch{min-width:140px;justify-content:space-between}}
     727@media(prefers-reduced-motion:reduce){.itdna-host-power-knob,.itdna-host-power-switch,.itdna-host-power-track{transition:none}}
     728
     729/* v1.3.62 adaptive scheduler control */
     730.itdna-pacing-choice{display:flex;flex-wrap:wrap;gap:10px;align-items:center;border:1px solid #d7e5fc;background:#f3f7fe;border-radius:12px;padding:12px;margin:12px 0}.itdna-pacing-choice label{display:flex;flex-direction:column;gap:3px;flex:1;min-width:180px;color:#183661}.itdna-pacing-choice label small{font-weight:400;color:#596e91}.itdna-pacing-choice select{min-width:260px;max-width:100%;border-radius:8px;border:1px solid #b5ccef}.itdna-pacing-choice .description{flex-basis:100%;margin:0;font-size:12px;color:#5b6f92}
     731
     732/* v1.3.63 verified-capacity dashboard */
     733.itdna-capacity-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin:12px 0}
     734.itdna-capacity-cell{border:1px solid #d7e2f4;background:#fff;border-radius:10px;padding:11px 12px;display:flex;flex-direction:column;gap:6px}
     735.itdna-capacity-cell small{color:#637693;font-size:11px;font-weight:600}
     736.itdna-capacity-cell strong{color:#1f4bd4;font-size:22px}
     737.itdna-capacity-note{color:#566784;font-size:12px;line-height:1.6}
     738@media(max-width:650px){.itdna-capacity-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
     739
     740/* v1.3.74 Dashboard Master Power. Scoped: does not alter Hosting Guard. */
     741.itdna-master-heading{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
     742.itdna-master-heading h1{margin:0}
     743.itdna-master-header-switch{display:inline-flex;align-items:center;gap:9px;flex-wrap:wrap}
     744.itdna-master-toggle-form{display:inline-flex;margin:0}
     745.itdna-master-header-switch .itdna-host-power-switch{min-height:37px}
     746.itdna-master-paused-page{max-width:1100px;padding:10px 8px 30px}
     747.itdna-master-paused-top{background:#fff;border:1px solid #d5e1ec;padding:20px 24px;border-radius:13px;margin:18px 0}
     748.itdna-master-paused-top p{color:#576779;margin:9px 0 0}
     749.itdna-master-paused-panel{background:#fff;border:1px solid #d5e1ec;border-left:4px solid #6e859c;border-radius:9px;padding:22px 24px;line-height:1.7;max-width:950px}
     750.itdna-master-paused-panel h2{margin-top:0}
     751@media(max-width:620px){.itdna-master-heading{align-items:flex-start;flex-direction:column;gap:9px}}
     752
     753/* v1.3.76: four guarded speed sliders */
     754.itdna-speed-console-v2 .itdna-speed-form{display:block}
     755.itdna-speed-v2-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-top:16px}
     756.itdna-speed-v2-control{background:#f7f9fd;border:1px solid #d9e2ef;border-radius:12px;padding:15px;min-width:0}
     757.itdna-speed-v2-control label{display:block;padding-right:60px}.itdna-speed-v2-control label strong{display:block;font-size:14px;color:#183153}.itdna-speed-v2-control label small{display:block;margin:6px 0;color:#526985;font-size:11px;line-height:1.45}
     758.itdna-speed-v2-control{position:relative}.itdna-speed-v2-number{position:absolute;right:15px;top:13px;display:flex;align-items:center;gap:8px;font-size:22px;color:#1c4df0;font-weight:800}
     759.itdna-speed-v2-control input[type=range]{width:100%;display:block;cursor:pointer;margin:16px 0 5px;accent-color:#3459e8}
     760.itdna-speed-v2-range{display:flex;justify-content:space-between;font-size:11px;color:#62758f}.itdna-speed-v2-risk{font-size:12px}.itdna-speed-v2-risk.risk-low{color:#139b56}.itdna-speed-v2-risk.risk-mid{color:#e5a100}.itdna-speed-v2-risk.risk-high{color:#cf3030}
     761.itdna-speed-v2-footer{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin:15px 0}.itdna-speed-v2-footer .itdna-speed-health{flex:1;min-width:220px}.itdna-speed-v2-buttons{display:flex;flex-direction:column;gap:8px}.itdna-speed-v2-buttons .button{white-space:normal;min-height:36px}
     762.itdna-speed-v2-notice{background:#f6f8fc;border-left:3px solid #2a53da;border-radius:4px;padding:11px 13px;line-height:1.6;color:#3e526d;font-size:12px}
     763@media(max-width:800px){.itdna-speed-v2-grid{grid-template-columns:1fr}.itdna-speed-v2-footer{display:block}.itdna-speed-v2-buttons{margin-top:12px}}
     764
     765/* v1.3.77: visual speed risk and scoped CPU/RAM at each slider */
     766.itdna-speed-v2-control input[type=range].risk-low{accent-color:#169957}
     767.itdna-speed-v2-control input[type=range].risk-mid{accent-color:#d58b00}
     768.itdna-speed-v2-control input[type=range].risk-high{accent-color:#d33535}
     769.itdna-speed-v2-load{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:4px 12px;border-top:1px solid #d9e2ef;margin-top:9px;padding-top:8px;font-size:11px}
     770.itdna-speed-v2-load span.risk-low{color:#126f43;font-weight:700}
     771.itdna-speed-v2-load span.risk-mid{color:#955900;font-weight:700}
     772.itdna-speed-v2-load span.risk-high{color:#b3222c;font-weight:700}
     773.itdna-speed-v2-load small{color:#4a5870;font-size:10px}
     774
     775/* v1.3.79: Dashboard single-open accordion, first section open by default. */
     776.itdna-main[data-itdna-tab="dashboard"] .itdna-accordion-card{overflow:hidden}
     777.itdna-main[data-itdna-tab="dashboard"] .itdna-accordion-head{display:grid!important;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:12px;cursor:pointer;user-select:none}
     778.itdna-main[data-itdna-tab="dashboard"] .itdna-accordion-head>h2,.itdna-main[data-itdna-tab="dashboard"] .itdna-accordion-head>p{grid-column:1}
     779.itdna-main[data-itdna-tab="dashboard"] .itdna-accordion-head .itdna-accordion-indicator{grid-column:2;grid-row:1 / span 2;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:999px;border:1px solid #d7e3f4;background:#f7fbff;color:#284d8f;font-size:20px;line-height:1;font-weight:700}
     780.itdna-main[data-itdna-tab="dashboard"] .itdna-accordion-head:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}
     781.itdna-main[data-itdna-tab="dashboard"] .itdna-accordion-card.itdna-acc-collapsed>.itdna-card-body{display:none!important}
     782.itdna-main[data-itdna-tab="dashboard"] .itdna-accordion-card.itdna-acc-collapsed>.itdna-card-head{border-bottom:0!important}
     783.itdna-main[data-itdna-tab="dashboard"] .itdna-accordion-card.itdna-acc-open>.itdna-card-head{background:#f8fbff!important}
     784.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console{padding:0!important}
     785.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console>.itdna-speed-heading{padding:15px 20px!important;margin:0!important;grid-template-columns:minmax(0,1fr) auto 28px!important;gap:10px!important}
     786.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console>.itdna-speed-heading>div{grid-column:1;min-width:0}
     787.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console>.itdna-speed-heading>.itdna-speed-chip{grid-column:2;grid-row:1}
     788.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console>.itdna-speed-heading>.itdna-accordion-indicator{grid-column:3;grid-row:1}
     789.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console>.itdna-speed-body{padding:14px 20px 16px!important}
     790.itdna-speed-effective{border:1px solid #fed7aa;background:#fff7ed;color:#92400e;padding:9px 12px;border-radius:9px;font-size:12px;line-height:1.6;margin-bottom:12px}
     791@media(max-width:600px){.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console>.itdna-speed-heading{padding:12px 14px!important;grid-template-columns:minmax(0,1fr) 26px!important}.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console>.itdna-speed-heading>.itdna-speed-chip{display:none}.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console>.itdna-speed-heading>.itdna-accordion-indicator{grid-column:2}.itdna-main[data-itdna-tab="dashboard"] .itdna-speed-console>.itdna-speed-body{padding:12px 14px!important}}
     792
     793/* 1.3.96: One universal serial background worker and one millisecond control. */
     794.itdna-single-worker-console .itdna-card-body{padding:20px 24px}
     795.itdna-single-speed-choice{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;margin:12px 0 22px}
     796.itdna-single-speed-choice strong{font-size:15px}
     797.itdna-single-speed-choice output{font-weight:800;font-size:24px;color:#284dea}
     798.itdna-single-gap-range{display:block;width:100%;max-width:900px;accent-color:#2856ee;cursor:pointer}
     799.itdna-single-gap-options{max-width:900px;display:flex;justify-content:space-between;gap:6px;font-size:12px;color:#68768c;margin:8px 0 18px}
     800.itdna-single-gap-note{max-width:900px;font-size:13px;line-height:1.6;color:#4b5563}
     801.itdna-single-gap-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px}
     802
     803.itdna-single-gap-options{max-width:900px;display:grid;grid-template-columns:repeat(11,minmax(48px,1fr));gap:2px;overflow-x:auto;white-space:nowrap;scrollbar-width:thin}
     804.itdna-single-gap-options span{font-size:11px;text-align:center;padding:4px 0}
     805@media(max-width:800px){.itdna-single-gap-options{grid-template-columns:repeat(11,minmax(58px,1fr))}}
     806
     807/* 1.3.99: speed-selection guidance, never a fabricated CPU/RAM utilisation indicator. */
     808.itdna-single-speed-form[data-speed-risk="green"]{--itdna-speed-risk:#199454;--itdna-speed-risk-bg:#e7f8ed;--itdna-speed-risk-border:#b2e2c2}
     809.itdna-single-speed-form[data-speed-risk="yellow"]{--itdna-speed-risk:#b67705;--itdna-speed-risk-bg:#fff7e2;--itdna-speed-risk-border:#f0d396}
     810.itdna-single-speed-form[data-speed-risk="red"]{--itdna-speed-risk:#c62336;--itdna-speed-risk-bg:#fff0f1;--itdna-speed-risk-border:#ffc0c7}
     811.itdna-single-speed-form .itdna-single-gap-range{accent-color:var(--itdna-speed-risk,#199454)}
     812.itdna-single-speed-form .itdna-single-speed-choice output{color:var(--itdna-speed-risk,#199454)}
     813.itdna-single-speed-warning{max-width:900px;padding:10px 12px;border:1px solid var(--itdna-speed-risk-border,#b2e2c2);border-left:4px solid var(--itdna-speed-risk,#199454);border-radius:7px;background:var(--itdna-speed-risk-bg,#e7f8ed);color:#304056;font-size:12px;line-height:1.5;margin:12px 0}
     814
     815/* v1.4.00: unmistakable live speed colours across WP themes and browsers. */
     816.itdna-main .itdna-single-speed-form input.itdna-single-gap-range[type="range"]{
     817  -webkit-appearance:none!important;appearance:none!important;
     818  background:var(--itdna-speed-risk,#199454)!important;
     819  accent-color:var(--itdna-speed-risk,#199454)!important;
     820  height:8px!important;border:0!important;border-radius:99px!important;
     821  padding:0!important;box-shadow:none!important;outline-offset:5px;
     822}
     823.itdna-single-speed-form input.itdna-single-gap-range[type="range"]::-webkit-slider-runnable-track{
     824  height:8px!important;background:var(--itdna-speed-risk,#199454)!important;border-radius:99px!important;
     825}
     826.itdna-single-speed-form input.itdna-single-gap-range[type="range"]::-webkit-slider-thumb{
     827  -webkit-appearance:none!important;appearance:none!important;width:17px;height:17px;
     828  background:var(--itdna-speed-risk,#199454)!important;border:3px solid #fff!important;
     829  border-radius:50%!important;margin-top:-4.5px;box-shadow:0 0 0 1px var(--itdna-speed-risk,#199454);
     830}
     831.itdna-single-speed-form input.itdna-single-gap-range[type="range"]::-moz-range-track{
     832  background:var(--itdna-speed-risk,#199454)!important;height:8px!important;border:0;border-radius:99px;
     833}
     834.itdna-single-speed-form input.itdna-single-gap-range[type="range"]::-moz-range-thumb{
     835  background:var(--itdna-speed-risk,#199454)!important;border:3px solid #fff!important;
     836  width:13px;height:13px;border-radius:50%!important;
     837}
     838.itdna-main .itdna-single-speed-form .itdna-single-speed-choice output{color:var(--itdna-speed-risk,#199454)!important}
     839.itdna-main .itdna-single-speed-form .itdna-single-speed-warning{
     840  background:var(--itdna-speed-risk-bg,#e7f8ed)!important;
     841  border-color:var(--itdna-speed-risk-border,#b2e2c2)!important;
     842  border-left-color:var(--itdna-speed-risk,#199454)!important;
     843}
     844
     845
     846/* v1.4.01: time gap uses the identical server-side risk thresholds as speed. */
     847.itdna-single-speed-current{display:flex;align-items:flex-end;flex-direction:column;gap:7px;max-width:100%}
     848.itdna-single-speed-time{display:inline-flex;align-items:center;flex-wrap:wrap;gap:7px;border:2px solid currentColor;border-radius:11px;padding:7px 11px;background:var(--itdna-speed-risk-bg,#e7f8ed);color:var(--itdna-speed-risk,#199454);font-size:13px;font-weight:700;line-height:1.35;transition:background-color .12s,color .12s,border-color .12s}
     849.itdna-single-speed-time strong{font-size:17px;font-variant-numeric:tabular-nums;white-space:nowrap}
     850.itdna-single-speed-time [data-event-gap-severity]{font-size:10px;font-weight:850;border-radius:5px;padding:3px 6px;background:var(--itdna-speed-risk,#199454);color:#fff;letter-spacing:.04em}
     851.itdna-main .itdna-single-speed-form[data-speed-risk="red"] .itdna-single-speed-time,.itdna-main .itdna-single-speed-form[data-speed-risk="red"] .itdna-single-speed-choice output{color:#c62336!important;background-color:#fff0f1}
     852.itdna-main .itdna-single-speed-form[data-speed-risk="yellow"] .itdna-single-speed-time,.itdna-main .itdna-single-speed-form[data-speed-risk="yellow"] .itdna-single-speed-choice output{color:#946000!important;background-color:#fff7e2}
     853.itdna-main .itdna-single-speed-form[data-speed-risk="green"] .itdna-single-speed-time,.itdna-main .itdna-single-speed-form[data-speed-risk="green"] .itdna-single-speed-choice output{color:#14783f!important;background-color:#e7f8ed}
     854.itdna-main .itdna-single-speed-form .itdna-single-speed-choice output{padding:3px 7px;border-radius:6px}
     855.itdna-single-speed-form .itdna-single-gap-options span{color:#65768a}
     856.itdna-single-speed-form .itdna-single-gap-options span.itdna-gap-active{color:var(--itdna-speed-risk,#199454);font-weight:800;box-shadow:inset 0 -3px 0 var(--itdna-speed-risk,#199454)}
     857@media(max-width:600px){.itdna-single-speed-current{align-items:flex-start;width:100%}.itdna-single-speed-choice{align-items:flex-start;flex-direction:column}.itdna-single-speed-time{max-width:100%;box-sizing:border-box}}
     858
     859.itdna-self-test-intro{font-size:13px;line-height:1.6}
     860.itdna-self-test-checks{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:10px;margin:12px 0}
     861.itdna-self-test-check{padding:11px 13px;border:1px solid #d2d9e2;border-radius:9px;min-width:0;background:#f8fafc}
     862.itdna-self-test-check-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:7px}
     863.itdna-self-test-check-head strong{font-size:13px}
     864.itdna-self-test-check-head span{font-size:11px;font-weight:800;white-space:nowrap}
     865.itdna-self-test-check small{display:block;font-size:11px;line-height:1.5;overflow-wrap:anywhere;margin-top:5px}
     866.itdna-self-test-green{border-left:4px solid #199454;background:#f1faf5}
     867.itdna-self-test-red{border-left:4px solid #c62336;background:#fff6f6}
     868.itdna-self-test-neutral{border-left:4px solid #64748b;background:#f8fafc}
     869.itdna-self-test-green .itdna-self-test-check-head span{color:#14783f}
     870.itdna-self-test-red .itdna-self-test-check-head span{color:#c62336}
     871
     872
     873/* v1.4.04 — intuitive left-to-right speed controller; user-facing levels only.
     874 * The real scheduler, gap table, concurrency and security layers are not changed. */
     875.itdna-single-worker-console .itdna-single-speed-form{--itdna-speed-tone:#138f61;--itdna-speed-soft:#edf9f3;--itdna-speed-border:#b8e8d1}
     876.itdna-single-worker-console .itdna-single-speed-form[data-speed-risk="yellow"]{--itdna-speed-tone:#b47b0c;--itdna-speed-soft:#fff9e8;--itdna-speed-border:#f4dda0}
     877.itdna-single-worker-console .itdna-single-speed-form[data-speed-risk="red"]{--itdna-speed-tone:#cc304a;--itdna-speed-soft:#fff0f3;--itdna-speed-border:#ffc2cb}
     878.itdna-main .itdna-single-worker-console .itdna-card-body{padding:21px 24px 20px!important}
     879.itdna-speed-control-header{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;background:linear-gradient(112deg,#f7fbff 0%,#f4f8ff 58%,#fff 100%);padding:15px 18px;border:1px solid #e0eafa;border-radius:15px;margin:1px 0 20px}
     880.itdna-speed-selected{display:flex;min-width:0;flex-direction:column;gap:6px}
     881.itdna-speed-overline{color:#607187;letter-spacing:.09em;font-size:10px;font-weight:800}
     882.itdna-main .itdna-single-worker-console .itdna-speed-selected output{background:transparent!important;color:var(--itdna-speed-tone)!important;font-size:clamp(19px,2vw,25px);line-height:1.25;letter-spacing:-.02em;font-weight:850;padding:0!important;border-radius:0!important}
     883.itdna-speed-subline{font-size:11px;color:#65768b;line-height:1.45}
     884.itdna-speed-indicator{display:flex;flex-direction:column;align-items:flex-end;gap:6px}
     885.itdna-speed-pill{display:inline-flex;gap:7px;align-items:center;padding:8px 12px;border-radius:999px;border:1px solid var(--itdna-speed-border);background:var(--itdna-speed-soft);color:var(--itdna-speed-tone);font-size:11px;line-height:1.25;font-weight:850;letter-spacing:.035em;white-space:nowrap;transition:background-color .15s,color .15s,border-color .15s}
     886.itdna-speed-pill i{display:block;width:8px;height:8px;background:currentColor;border-radius:999px;box-shadow:0 0 0 3px rgba(120,135,150,.09);flex:0 0 8px}
     887.itdna-speed-indicator small{color:#6c7c91;font-weight:750;font-size:10px;letter-spacing:.08em;font-variant-numeric:tabular-nums}
     888.itdna-speed-direction{display:flex;justify-content:space-between;align-items:center;gap:12px;margin:6px 2px 14px;letter-spacing:.055em;font-size:12px;font-weight:850;color:#53667c}
     889.itdna-speed-direction>span:last-child{color:#c32e48;text-align:right}
     890.itdna-speed-direction small{font-weight:650;font-size:11px;letter-spacing:0;margin-left:4px;color:#75869a}
     891.itdna-speed-rail{position:relative;height:30px;max-width:100%;display:flex;align-items:center;margin:0 0 1px;--itdna-speed-progress:60%;isolation:isolate}
     892.itdna-speed-rail::before,.itdna-speed-rail::after{content:'';position:absolute;left:0;top:50%;height:12px;transform:translateY(-50%);border-radius:999px;pointer-events:none}
     893.itdna-speed-rail::before{right:0;border:1px solid #d6e2ed;background:linear-gradient(90deg,#edf3f9,#e4ebf4);box-shadow:inset 0 2px 3px rgba(20,35,55,.08)}
     894.itdna-speed-rail::after{width:var(--itdna-speed-progress);max-width:100%;background:linear-gradient(90deg,#149968 0%,var(--itdna-speed-tone) 100%);box-shadow:inset 0 1px 1px rgba(255,255,255,.2),0 2px 6px rgba(20,60,50,.11);transition:width .1s ease,background-color .15s ease;z-index:1}
     895.itdna-main .itdna-single-worker-console input.itdna-single-gap-range[type="range"]{position:relative!important;z-index:2!important;display:block!important;direction:ltr!important;-webkit-appearance:none!important;appearance:none!important;width:100%!important;max-width:100%!important;min-width:0!important;height:30px!important;margin:0!important;padding:0!important;border:0!important;border-radius:0!important;box-shadow:none!important;background:transparent!important;cursor:pointer!important;outline:none!important;accent-color:var(--itdna-speed-tone)!important;touch-action:pan-y}
     896.itdna-main .itdna-single-worker-console input.itdna-single-gap-range[type="range"]::-webkit-slider-runnable-track{height:12px!important;background:transparent!important;border:0!important;border-radius:999px!important}
     897.itdna-main .itdna-single-worker-console input.itdna-single-gap-range[type="range"]::-moz-range-track{height:12px!important;background:transparent!important;border:0!important;border-radius:999px!important}
     898.itdna-main .itdna-single-worker-console input.itdna-single-gap-range[type="range"]::-webkit-slider-thumb{-webkit-appearance:none!important;appearance:none!important;position:relative!important;width:26px!important;height:26px!important;border:4px solid #fff!important;border-radius:50%!important;margin-top:-7px!important;background:var(--itdna-speed-tone)!important;box-shadow:0 0 0 2px var(--itdna-speed-tone),0 3px 13px rgba(20,37,61,.22)!important;transition:box-shadow .15s ease,transform .15s ease}
     899.itdna-main .itdna-single-worker-console input.itdna-single-gap-range[type="range"]::-moz-range-thumb{width:18px!important;height:18px!important;border:4px solid #fff!important;border-radius:50%!important;background:var(--itdna-speed-tone)!important;box-shadow:0 0 0 2px var(--itdna-speed-tone),0 3px 13px rgba(20,37,61,.22)!important}
     900.itdna-main .itdna-single-worker-console input.itdna-single-gap-range[type="range"]:focus-visible{outline:3px solid #2563eb!important;outline-offset:5px!important;border-radius:999px!important}
     901.itdna-single-worker-console .itdna-single-gap-options{display:grid!important;grid-template-columns:repeat(11,minmax(0,1fr))!important;column-gap:1px!important;max-width:none!important;margin:6px 0 17px!important;overflow:visible!important;white-space:normal!important;align-items:start}
     902.itdna-single-worker-console .itdna-single-gap-options span{min-width:0;padding:6px 1px 8px!important;text-align:center!important;font-size:10px!important;line-height:1.3!important;font-weight:600;color:#718298!important;box-shadow:none!important;border-bottom:2px solid transparent}
     903.itdna-single-worker-console .itdna-single-gap-options span.itdna-gap-active{color:var(--itdna-speed-tone)!important;font-weight:850!important;background:var(--itdna-speed-soft);border-bottom:2px solid var(--itdna-speed-tone);border-radius:6px 6px 0 0;box-shadow:none!important}
     904.itdna-main .itdna-single-worker-console .itdna-single-speed-warning{max-width:none!important;margin:10px 0 0!important;padding:12px 14px!important;border:1px solid var(--itdna-speed-border)!important;border-left:4px solid var(--itdna-speed-tone)!important;border-radius:10px!important;background:var(--itdna-speed-soft)!important;color:#273a50!important;font-size:12.5px!important;line-height:1.6!important}
     905.itdna-main .itdna-single-worker-console .itdna-single-gap-note{max-width:none!important;color:#62758c!important;font-size:11.5px!important;line-height:1.6!important;margin:11px 0 0!important}
     906.itdna-speed-preview-note{display:flex;align-items:center;gap:4px;color:#925b06;background:#fff7e7;border:1px solid #f3dfae;padding:9px 12px;border-radius:8px;margin:10px 0 0;font-size:12px;font-weight:650}
     907.itdna-speed-preview-note[hidden]{display:none!important}
     908.itdna-single-worker-console .itdna-single-gap-actions{margin-top:17px;gap:10px}
     909.itdna-main .itdna-single-worker-console .itdna-single-gap-actions .button{border-radius:9px!important;min-height:38px!important;padding:8px 16px!important;font-weight:750!important;box-shadow:0 3px 8px rgba(27,65,96,.06)}
     910.itdna-main .itdna-single-worker-console .itdna-single-gap-actions .button-primary{background:#214ed5!important;color:#fff!important;border-color:#214ed5!important}
     911@media(max-width:760px){.itdna-speed-control-header{padding:14px;gap:12px}.itdna-single-worker-console .itdna-single-gap-options span{font-size:9px!important}.itdna-single-worker-console .itdna-single-gap-options span:nth-child(2),.itdna-single-worker-console .itdna-single-gap-options span:nth-child(3),.itdna-single-worker-console .itdna-single-gap-options span:nth-child(4),.itdna-single-worker-console .itdna-single-gap-options span:nth-child(5),.itdna-single-worker-console .itdna-single-gap-options span:nth-child(6),.itdna-single-worker-console .itdna-single-gap-options span:nth-child(8),.itdna-single-worker-console .itdna-single-gap-options span:nth-child(9),.itdna-single-worker-console .itdna-single-gap-options span:nth-child(10){visibility:hidden}.itdna-single-worker-console .itdna-single-gap-options span.itdna-gap-active{visibility:visible!important}}
     912@media(max-width:490px){.itdna-main .itdna-single-worker-console .itdna-card-body{padding:14px!important}.itdna-speed-direction{font-size:11px}.itdna-speed-direction small{display:block;margin:3px 0 0;font-size:10px}.itdna-speed-overline{font-size:9px}.itdna-speed-control-header{align-items:flex-start}.itdna-speed-indicator{align-items:flex-start}.itdna-speed-pill{padding:7px 9px;font-size:10px}.itdna-main .itdna-single-worker-console .itdna-speed-selected output{font-size:19px!important}}
     913@media(prefers-reduced-motion:reduce){.itdna-speed-rail::after,.itdna-speed-pill{transition:none!important}}
     914
     915/* v1.4.06 - Easy Setup is a one-time default; user overrides are explicitly explained. */
     916.itdna-easy-manual-note{margin:8px 0 0!important;color:#31516e;font-size:12px;line-height:1.65;max-width:800px}.itdna-easy-manual-note strong{color:#155e75}
     917
     918/* v1.4.17: Search across every Turbo Cache admin tab. Read-only; no user settings are modified. */
     919.itdna-sidebar .itdna-global-search{position:relative;margin:0 3px 14px;padding:10px 9px 9px;border:1px solid rgba(117,161,225,.29);border-radius:11px;background:rgba(255,255,255,.055);color:#e8f0ff;box-sizing:border-box}
     920.itdna-global-search>label{display:flex;justify-content:space-between;gap:6px;align-items:center;font-size:12px;font-weight:700;margin-bottom:7px;color:#f2f7ff}
     921.itdna-global-search>label span{font-size:10px;color:#adc5ee;font-weight:600;padding:2px 5px;border:1px solid #4c6588;border-radius:5px;white-space:nowrap}
     922.itdna-search-input-wrap{display:flex;align-items:center;gap:5px;background:#fff;border-radius:8px;border:2px solid transparent;padding:0 7px;min-height:39px;box-sizing:border-box}
     923.itdna-search-input-wrap:focus-within{border-color:#6eafff;box-shadow:0 0 0 2px rgba(77,149,255,.16)}
     924.itdna-search-input-wrap>span{color:#5e789e;font-size:21px;line-height:1}
     925.itdna-search-input-wrap input[type=search]{display:block;min-width:0;width:100%;height:35px;min-height:0;margin:0!important;padding:5px 2px!important;color:#193357!important;border:0!important;outline:none!important;box-shadow:none!important;background:#fff!important;font-size:12px!important}
     926.itdna-search-input-wrap input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
     927.itdna-search-input-wrap button{flex:0 0 19px;background:none;border:0;padding:1px;color:#526b8e;cursor:pointer;font-size:20px;line-height:1}
     928.itdna-search-input-wrap button[hidden],.itdna-search-results[hidden]{display:none!important}
     929.itdna-search-hint{font-size:10.5px;color:#a8bedc;margin:6px 2px 0;line-height:1.4}
     930.itdna-search-results{display:flex;flex-direction:column;max-height:300px;overflow:auto;overscroll-behavior:contain;margin-top:8px;padding:4px;background:#0f2647;border:1px solid #365577;border-radius:9px;box-shadow:0 10px 22px rgba(0,0,0,.17)}
     931.itdna-search-result{display:flex;flex-direction:column;gap:3px;text-decoration:none!important;padding:8px;border-radius:6px;color:#e8f3ff!important;border-bottom:1px solid rgba(255,255,255,.06)}
     932.itdna-search-result:hover,.itdna-search-result:focus-visible,.itdna-search-result[aria-selected=true]{background:#254c78!important;color:#fff!important;outline:1px solid rgba(255,255,255,.22)}
     933.itdna-search-result-title{font-weight:700;font-size:11.5px;line-height:1.3;overflow-wrap:anywhere}
     934.itdna-search-result small{font-size:10px;color:#b6d1ee;line-height:1.35;overflow-wrap:anywhere}
     935.itdna-search-empty{color:#d0ddeb;padding:11px 8px;font-size:11px;line-height:1.5}
     936.itdna-search-more{width:100%;min-height:32px;padding:7px;background:#173b64;border:1px solid #3c6896;border-radius:6px;color:#e6f2ff;font-size:11px;cursor:pointer}
     937.itdna-search-more:hover{background:#2b547d}
     938.itdna-main .itdna-search-focus{outline:3px solid #ffba49!important;outline-offset:3px;background-color:#fff8df!important;border-radius:8px;scroll-margin:100px}
     939.itdna-main .itdna-card.itdna-search-focus{outline-offset:2px}
     940@media (max-width:782px){.itdna-sidebar .itdna-global-search{max-width:none}.itdna-search-results{max-height:230px}}
     941
     942/* v1.4.18: pending self-test probes are not safety failures or verified passes. */
     943.itdna-self-test-pending{border-left:4px solid #d69e1f;background:#fff9e9}
     944.itdna-self-test-pending .itdna-self-test-check-head span{color:#905b00}
     945
     946/* v1.4.54: compact one-line sidebar navigation, layout-only change. */
     947/* Give long tab labels room without reducing the text size or touching page content. */
     948.itdna-shell{grid-template-columns:270px minmax(0,1fr)!important}
     949.itdna-sidebar nav a{white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important;min-width:0!important;min-height:18px!important}
     950.itdna-sidebar nav a>span{flex:0 0 17px!important;width:17px!important}
     951@media (max-width:1100px) and (min-width:901px){.itdna-shell{grid-template-columns:255px minmax(0,1fr)!important}}
     952@media (max-width:900px) and (min-width:783px){.itdna-shell{grid-template-columns:245px minmax(0,1fr)!important}}
     953@media (max-width:782px){.itdna-shell{display:block!important}.itdna-sidebar nav{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))!important}}
     954
     955/* v1.4.64: Turbo 10x settings IA — scoped to this tab; no other UI is changed. */
     956#itdna-turbo-10x-duper-speed>.itdna-card-body{padding:16px!important}
     957#itdna-turbo-10x-duper-speed .itdna-wsa-section{
     958  border:1px solid #e0e7f0;border-radius:11px;padding:16px 18px;
     959  margin:0 0 14px;box-sizing:border-box;min-width:0;overflow-wrap:anywhere;
     960  background:#fafcff;box-shadow:0 1px 2px rgba(28,49,84,.022)
     961}
     962#itdna-turbo-10x-duper-speed .itdna-wsa-section-status{background:#f3f8ff;border-color:#dce8f8}
     963#itdna-turbo-10x-duper-speed .itdna-wsa-section-connection{background:#f5fbf7;border-color:#d9ebdf}
     964#itdna-turbo-10x-duper-speed .itdna-wsa-section-sync{background:#fffaf3;border-color:#f0e6d3}
     965#itdna-turbo-10x-duper-speed .itdna-wsa-section-delivery{background:#f5f9ff;border-color:#dfe9f7}
     966#itdna-turbo-10x-duper-speed .itdna-wsa-section-cache{background:#f7f8fd;border-color:#e2e4f1}
     967#itdna-turbo-10x-duper-speed .itdna-wsa-section-oauth{background:#f8f7fc;border-color:#e6e1f0}
     968#itdna-turbo-10x-duper-speed .itdna-wsa-section-cleanup{background:#fffafa;border-color:#f0e1e1}
     969#itdna-turbo-10x-duper-speed .itdna-wsa-section>h3{
     970  margin:0 0 8px!important;padding:0 0 9px!important;
     971  border-bottom:1px solid rgba(62,83,122,.12);
     972  color:#1e3354!important;font-size:15px!important;font-weight:700!important;
     973  line-height:1.4!important;letter-spacing:0!important
     974}
     975#itdna-turbo-10x-duper-speed .itdna-wsa-section>h3 small{font-weight:400;color:#657792;font-size:11.5px}
     976#itdna-turbo-10x-duper-speed .itdna-wsa-section-intro{margin:2px 0 14px;color:#63728b;font-size:12px;line-height:1.65}
     977#itdna-turbo-10x-duper-speed .itdna-wsa-section .itdna-grid-4{
     978  display:grid!important;grid-template-columns:repeat(auto-fit,minmax(205px,1fr))!important;
     979  gap:11px!important;margin:10px 0 14px!important;align-items:stretch!important
     980}
     981#itdna-turbo-10x-duper-speed .itdna-wsa-section .itdna-grid-4>.itdna-field{
     982  min-width:0!important;max-width:none!important;margin:0!important;padding:11px 12px!important;
     983  background:rgba(255,255,255,.9);border:1px solid #e2e9f2;border-radius:9px;
     984  color:#274268!important;line-height:1.55!important;box-sizing:border-box
     985}
     986#itdna-turbo-10x-duper-speed .itdna-wsa-section .itdna-grid-4>.itdna-field strong{
     987  display:block;margin-bottom:5px!important;font-size:12.5px!important;line-height:1.4!important
     988}
     989#itdna-turbo-10x-duper-speed .itdna-wsa-section .itdna-grid-4 input{
     990  width:100%!important;min-width:0!important;max-width:100%!important;margin-top:6px!important
     991}
     992#itdna-turbo-10x-duper-speed .itdna-wsa-section .description{
     993  color:#596a82!important;line-height:1.65!important;font-size:12px!important
     994}
     995#itdna-turbo-10x-duper-speed .itdna-wsa-section .itdna-info{
     996  background:rgba(255,255,255,.88)!important;border:1px solid #e2e9f2;
     997  border-radius:9px;padding:12px!important;line-height:1.75!important;
     998  margin:10px 0!important;overflow-wrap:anywhere
     999}
     1000#itdna-turbo-10x-duper-speed .itdna-wsa-section .itdna-warn{
     1001  border:1px solid #f0d5bc;background:#fff8ee;padding:11px 12px;border-radius:8px;
     1002  overflow-wrap:anywhere
     1003}
     1004#itdna-turbo-10x-duper-speed .itdna-wsa-section code{white-space:normal;overflow-wrap:anywhere}
     1005#itdna-turbo-10x-duper-speed .itdna-wsa-section .itdna-actions{
     1006  gap:8px!important;margin:12px 0 8px!important;align-items:center!important
     1007}
     1008#itdna-turbo-10x-duper-speed .itdna-wsa-section button{white-space:normal!important;text-align:center!important}
     1009#itdna-turbo-10x-duper-speed .itdna-wsa-subdetails{
     1010  margin:10px 0 2px;background:rgba(255,255,255,.88);
     1011  border:1px solid #e0e7f1;border-radius:9px;padding:0 12px;min-width:0
     1012}
     1013#itdna-turbo-10x-duper-speed .itdna-wsa-subdetails>summary{
     1014  display:list-item;cursor:pointer;padding:12px 4px;color:#284e86;
     1015  font-weight:650;font-size:12.5px;line-height:1.5
     1016}
     1017#itdna-turbo-10x-duper-speed .itdna-wsa-subdetails[open]{padding-bottom:12px}
     1018#itdna-turbo-10x-duper-speed .itdna-wsa-subdetails>summary:focus-visible{outline:2px solid #4387dc;outline-offset:2px}
     1019#itdna-turbo-10x-duper-speed .itdna-wsa-section>p>label{line-height:1.7}
     1020#itdna-turbo-10x-duper-speed .itdna-wsa-section-cache .itdna-info{margin:10px 0!important}
     1021/* Guide is a separate lower accordion; each language's steps are legible rows. */
     1022#itdna-workers-setup-guide>.itdna-card-body{padding:17px!important}
     1023#itdna-workers-setup-guide .itdna-wsa-guide-hi,
     1024#itdna-workers-setup-guide .itdna-wsa-guide-en{min-width:0;line-height:1.7;font-size:12.5px;overflow-wrap:anywhere}
     1025#itdna-workers-setup-guide .itdna-wsa-guide-hi>p,
     1026#itdna-workers-setup-guide .itdna-wsa-guide-en>p{
     1027  margin-bottom:12px!important;padding:11px 13px!important;
     1028  background:#f4f9ff;border:1px solid #deebf8;border-radius:8px;line-height:1.7
     1029}
     1030#itdna-workers-setup-guide .itdna-wsa-guide-hi>h3,
     1031#itdna-workers-setup-guide .itdna-wsa-guide-en>h3{font-size:14px!important;color:#1e3354;margin:17px 0 12px!important}
     1032#itdna-workers-setup-guide .itdna-wsa-guide-hi>ol,
     1033#itdna-workers-setup-guide .itdna-wsa-guide-en>ol{
     1034  display:grid;gap:10px;list-style:decimal!important;
     1035  padding:0 0 0 26px!important;margin:12px 0 14px!important
     1036}
     1037#itdna-workers-setup-guide .itdna-wsa-guide-hi>ol>li,
     1038#itdna-workers-setup-guide .itdna-wsa-guide-en>ol>li{
     1039  padding:12px 14px!important;margin:0!important;border:1px solid #e0e7f0;
     1040  border-radius:9px;line-height:1.72;background:#f5f9ff
     1041}
     1042#itdna-workers-setup-guide .itdna-wsa-guide-hi>ol>li:nth-child(even),
     1043#itdna-workers-setup-guide .itdna-wsa-guide-en>ol>li:nth-child(even){background:#f6faf7;border-color:#dce9df}
     1044#itdna-workers-setup-guide .itdna-wsa-guide-hi>ol>li::marker,
     1045#itdna-workers-setup-guide .itdna-wsa-guide-en>ol>li::marker{font-weight:700;color:#325da0}
     1046#itdna-workers-setup-guide a{overflow-wrap:anywhere}
     1047@media (max-width:800px){
     1048  #itdna-turbo-10x-duper-speed>.itdna-card-body{padding:10px!important}
     1049  #itdna-turbo-10x-duper-speed .itdna-wsa-section{padding:12px!important;margin-bottom:11px}
     1050  #itdna-turbo-10x-duper-speed .itdna-wsa-section .itdna-grid-4{grid-template-columns:1fr!important}
     1051  #itdna-workers-setup-guide>.itdna-card-body{padding:11px!important}
     1052}
     1053
     1054/* v1.4.84: borderline cache-probe regressions stay amber, never false red. */
     1055.itdna-easy-verdict.warn{border:1px solid #edcd80;background:#fffbeb;color:#80550b}
     1056
     1057/* Free edition · native in-row premium preview without changing settings layout. */
     1058.itdna-wrap .itdna-pro-badge{display:inline-flex;align-items:center;margin:0 5px;padding:2px 7px;border-radius:6px;background:#ede9fe;color:#5b21b6;font-size:10px;line-height:1.4;font-weight:800;letter-spacing:.08em;vertical-align:middle}
     1059.itdna-wrap .itdna-pro-link{display:inline;font-size:12px;font-weight:700;color:#5b21b6;text-decoration:none}
     1060.itdna-wrap .itdna-pro-link:hover{text-decoration:underline}
     1061.itdna-wrap .itdna-field input:disabled,.itdna-wrap .itdna-field select:disabled{opacity:.75;cursor:not-allowed}
  • indiatvdna-turbo-cache-lite/trunk/assets/admin.js

    r3729643 r3763637  
    1 (function () {
    2     'use strict';
    3     if (!window.itdnaTcLite) return;
    4 
    5     function findMetric(label) {
    6         var cards = document.querySelectorAll('#itdna-live-stats .itdna-metric');
    7         for (var i = 0; i < cards.length; i++) {
    8             var first = cards[i].querySelector('span');
    9             if (first && first.textContent.replace(/PRO/g, '').trim() === label) return cards[i];
     1(function(){
     2'use strict';
     3if (window.__itdnaTurboAdminLoaded) return;
     4window.__itdnaTurboAdminLoaded = true;
     5window.ITDNA_TC_ADMIN_GEN=window.ITDNA_TC_ADMIN_GEN||0;
     6var itdnaBusyHideTimer=null;
     7function itdnaBusyNotice(message){
     8  var el=document.getElementById('itdna-global-busy');
     9  if(!el){
     10    el=document.createElement('div');el.id='itdna-global-busy';el.className='itdna-global-busy';el.setAttribute('role','status');el.setAttribute('aria-live','polite');
     11    el.innerHTML='<span class="itdna-busy-spinner" aria-hidden="true"></span><span class="itdna-busy-text"></span>';
     12    document.body.appendChild(el);
     13  }
     14  if(itdnaBusyHideTimer){clearTimeout(itdnaBusyHideTimer);itdnaBusyHideTimer=null;}
     15  var label=el.querySelector('.itdna-busy-text');if(label)label.textContent=message||'Working…';
     16  el.classList.add('show');
     17}
     18function itdnaBusyClear(delay){
     19  var run=function(){var el=document.getElementById('itdna-global-busy');if(el)el.classList.remove('show');};
     20  if(delay){itdnaBusyHideTimer=setTimeout(run,delay);}else run();
     21}
     22function itdnaWorkingText(label){
     23  var t=String(label||'').trim();
     24  if(/self[- ]?test|test/i.test(t))return 'Testing…';
     25  if(/purge|clear/i.test(t))return 'Purging…';
     26  if(/save|apply/i.test(t))return 'Saving…';
     27  if(/scan|analy/i.test(t))return 'Analyzing…';
     28  if(/preload|warm/i.test(t))return 'Starting…';
     29  return 'Working…';
     30}
     31function itdnaBindGlobalActionFeedback(){
     32  if(window.__itdnaActionFeedbackBound)return;window.__itdnaActionFeedbackBound=1;
     33  document.addEventListener('click',function(e){
     34    if(e.defaultPrevented||e.button!==0)return;
     35    var link=e.target&&e.target.closest?e.target.closest('a.itdna-action-link, #wp-admin-bar-itdna-turbo-cache-purge > a'):null;
     36    if(!link)return;
     37    if(link.getAttribute('data-itdna-working')==='1'){e.preventDefault();return;}
     38    var original=String(link.textContent||'').trim();
     39    link.setAttribute('data-itdna-working','1');link.setAttribute('aria-busy','true');link.classList.add('itdna-is-working');
     40    if(!link.getAttribute('data-itdna-original-label'))link.setAttribute('data-itdna-original-label',original);
     41    var working=itdnaWorkingText(original);link.textContent=working;itdnaBusyNotice(working+' Please wait — the request is running.');
     42  });
     43  document.addEventListener('submit',function(e){
     44    if(e.defaultPrevented)return;
     45    var form=e.target;if(!form||!form.closest||!form.closest('.itdna-wrap'))return;
     46    if(form.getAttribute('data-itdna-submitting')==='1'){e.preventDefault();return;}
     47    form.setAttribute('data-itdna-submitting','1');
     48    var btn=(e.submitter&&e.submitter.matches&&e.submitter.matches('button,input[type=submit]'))?e.submitter:form.querySelector('button[type=submit],input[type=submit]');
     49    if(btn){
     50      var old=(btn.value||btn.textContent||'Save');
     51      btn.setAttribute('data-itdna-original-label',old);
     52      // A disabled submitter is not a successful form control. Preserve its exact
     53      // name/value before disabling it so named actions such as Cloudflare
     54      // verify/detect, CDN test and LiteSpeed verify still reach PHP.
     55      var submitName=btn.getAttribute('name');
     56      if(submitName){
     57        var mirror=document.createElement('input');
     58        mirror.type='hidden';mirror.name=submitName;mirror.value=btn.value||'';
     59        mirror.setAttribute('data-itdna-submit-mirror','1');
     60        form.appendChild(mirror);
     61      }
     62      btn.disabled=true;
     63      if(btn.tagName==='INPUT')btn.value='Saving…';else btn.textContent='Saving…';
     64    }
     65    itdnaBusyNotice('Saving… Please wait — your changes are being applied.');
     66  });
     67}
     68function itdnaDedupeNotices(){
     69  var nodes=Array.prototype.slice.call(document.querySelectorAll('.itdna-main .itdna-notice, #wpbody-content .notice'));
     70  var seen={};
     71  nodes.forEach(function(n){
     72    var key=String(n.textContent||'').replace(/\s+/g,' ').trim();if(!key)return;
     73    var isSelf=/^Cache self-test\s*[—-]/i.test(key);
     74    var failed=isSelf&&/(FAILED BYPASS|NOT VERIFIED|\bFAILED\b|\bERROR\b)/i.test(key);
     75    if(failed){n.classList.remove('success','notice-success');n.classList.add('error');if(n.classList.contains('notice'))n.classList.add('notice-error');}
     76    if(!isSelf && !n.classList.contains('itdna-notice'))return;
     77    var rank=(n.classList.contains('error')||n.classList.contains('notice-error'))?3:((n.classList.contains('warning')||n.classList.contains('notice-warning'))?2:1);
     78    if(!seen[key]){seen[key]={node:n,rank:rank};return;}
     79    if(rank>seen[key].rank){if(seen[key].node&&seen[key].node.parentNode)seen[key].node.parentNode.removeChild(seen[key].node);seen[key]={node:n,rank:rank};}
     80    else if(n.parentNode)n.parentNode.removeChild(n);
     81  });
     82}
     83function itdnaInitAdminMain(){
     84  var gen=++window.ITDNA_TC_ADMIN_GEN;
     85  var viewMain=document.querySelector('.itdna-main');
     86  if(!viewMain)return;
     87  itdnaDedupeNotices();
     88  var gapPanel=viewMain.querySelector('[data-itdna-single-speed]');
     89  if(gapPanel){
     90    // The slider now progresses naturally: LEFT = lower speed, RIGHT = higher speed.
     91    // Reverse ONLY its presentation. Saved scheduler milliseconds remain the same.
     92    var gapValues=[2000,1000,900,800,700,600,500,400,300,200,100];
     93    var speedNames=['Minimum Speed','Eco','Eco Plus','Gentle','Steady','Smooth','Balanced · Best','Very Fast','Ultra Fast','Extreme','Max Speed'];
     94    var slider=gapPanel.querySelector('[data-event-gap-slider]');
     95    var stored=gapPanel.querySelector('[data-event-gap-value]');
     96    var output=gapPanel.querySelector('[data-event-gap-output]');
     97    var riskForm=gapPanel.querySelector('[data-speed-risk]');
     98    var riskNote=gapPanel.querySelector('[data-speed-risk-note]');
     99    var status=gapPanel.querySelector('[data-event-gap-severity]');
     100    var level=gapPanel.querySelector('[data-speed-level]');
     101    var rail=gapPanel.querySelector('.itdna-speed-rail');
     102    var preview=gapPanel.querySelector('[data-speed-preview-note]');
     103    var gapTicks=gapPanel.querySelectorAll('.itdna-single-gap-options span');
     104    function syncGap(){
     105      if(!slider||!stored)return;
     106      var index=Math.max(0,Math.min(10,Number(slider.value)||0));
     107      stored.value=String(gapValues[index]);
     108      if(output)output.textContent=speedNames[index];
     109      slider.setAttribute('aria-valuetext',speedNames[index]);
     110      var risk=index>=8?'red':(index===7?'yellow':'green');
     111      if(riskForm)riskForm.setAttribute('data-speed-risk',risk);
     112      if(rail)rail.style.setProperty('--itdna-speed-progress',String(index*10)+'%');
     113      if(status)status.textContent=risk==='red'?'HIGH INTENSITY':(risk==='yellow'?'USE WITH CARE':(index===6?'RECOMMENDED':'LOWER ACTIVITY'));
     114      if(level)level.textContent='LEVEL '+String(index+1)+' / 11';
     115      Array.prototype.forEach.call(gapTicks,function(tick,i){tick.classList.toggle('itdna-gap-active',i===index);});
     116      if(riskNote)riskNote.textContent=risk==='red'
     117        ? '⚠ High-speed setting. Background jobs may start more frequently. Watch your hosting CPU/RAM and PHP errors.'
     118        : (risk==='yellow'
     119          ? '⚠ Faster processing selected. Check hosting resource usage during heavy background work.'
     120          : (index===6
     121            ? '✓ Recommended balance for most sites. A good starting point for background optimization.'
     122            : '✓ Lower background activity selected. Jobs may start less frequently.'));
     123      var initial=riskForm?Number(riskForm.getAttribute('data-original-speed-step')):index;
     124      if(preview)preview.hidden=(index===initial);
     125    }
     126    if(slider){slider.addEventListener('input',syncGap);slider.addEventListener('change',syncGap);syncGap();}
     127  }
     128  function alive(){return gen===window.ITDNA_TC_ADMIN_GEN&&viewMain.isConnected;}
     129  viewMain.querySelectorAll('input[type=password]').forEach(function(el){
     130    var wrap=document.createElement('div');wrap.className='itdna-password-wrap';
     131    el.parentNode.insertBefore(wrap,el);wrap.appendChild(el);
     132    var b=document.createElement('button');b.type='button';b.className='button';b.textContent='Show';b.style.marginLeft='8px';
     133    b.addEventListener('click',function(){var show=el.type==='password';el.type=show?'text':'password';b.textContent=show?'Hide':'Show';});wrap.appendChild(b);
     134  });
     135  viewMain.querySelectorAll('[data-itdna-speed-restore]').forEach(function(btn){
     136    btn.addEventListener('click',function(ev){
     137      if(!window.confirm('Restore recommended background speed? Existing cache and media will not be cleared.'))ev.preventDefault();
     138    });
     139  });
     140  viewMain.querySelectorAll('button, a.itdna-action-link').forEach(function(btn){
     141    if(!btn.hasAttribute('data-itdna-speed-restore') && /purge|cleanup|reset/i.test(btn.textContent))btn.addEventListener('click',function(e){
     142      if(/reset/i.test(btn.textContent)&&!window.confirm('Restore safe defaults and clear local cache?'))e.preventDefault();
     143    });
     144  });
     145
     146
     147  function itdnaBindCategoryAccordions(root){
     148    if(!root) return;
     149    var tab=(root.getAttribute('data-itdna-tab')||'').toLowerCase();
     150    // The Dashboard uses the same single-open accordion as other tabs.
     151    // Its first section (Smart Background Speed) is expanded by default.
     152
     153    var cards=Array.prototype.slice.call(root.querySelectorAll('.itdna-card')).filter(function(card){
     154      if(card.closest('[data-itdna-auto-choice]')) return false;
     155      if(card.classList.contains('itdna-category-host') || card.querySelector(':scope > .itdna-card-body > .itdna-category-stack')) return false;
     156      return card.querySelector(':scope > .itdna-card-head') && card.querySelector(':scope > .itdna-card-body');
     157    });
     158    var categories=Array.prototype.slice.call(root.querySelectorAll('.itdna-option-category'));
     159
     160    function setCard(card,open){
     161      var head=card.querySelector(':scope > .itdna-card-head');
     162      var body=card.querySelector(':scope > .itdna-card-body');
     163      var indicator=head?head.querySelector('.itdna-accordion-indicator'):null;
     164      if(!head||!body)return;
     165      card.classList.toggle('itdna-acc-open',!!open);
     166      card.classList.toggle('itdna-acc-collapsed',!open);
     167      head.setAttribute('aria-expanded',open?'true':'false');
     168      if(indicator)indicator.textContent=open?'−':'+';
     169      body.hidden=!open;
     170    }
     171    function setCategory(cat,open){
     172      var trigger=cat.querySelector(':scope > .itdna-option-category-trigger');
     173      var body=cat.querySelector(':scope > .itdna-option-category-body');
     174      var icon=trigger?trigger.querySelector('.itdna-option-category-icon'):null;
     175      if(!trigger||!body)return;
     176      cat.classList.toggle('itdna-category-open',!!open);
     177      trigger.setAttribute('aria-expanded',open?'true':'false');
     178      if(icon)icon.textContent=open?'−':'+';
     179      body.hidden=!open;
     180    }
     181    function closeEverything(except){
     182      cards.forEach(function(card){if(card!==except)setCard(card,false);});
     183      categories.forEach(function(cat){if(cat!==except)setCategory(cat,false);});
     184    }
     185    function toggleUnit(unit,type){
     186      var open=type==='card'?unit.classList.contains('itdna-acc-open'):unit.classList.contains('itdna-category-open');
     187      if(open){
     188        if(type==='card')setCard(unit,false);else setCategory(unit,false);
     189        var stack=unit.closest('.itdna-category-stack')||unit.parentElement;
     190        if(stack)window.requestAnimationFrame(function(){try{stack.scrollIntoView({block:'nearest',behavior:'smooth'});}catch(err){}});
     191        return;
     192      }
     193      closeEverything(unit);
     194      if(type==='card')setCard(unit,true);else setCategory(unit,true);
     195      window.requestAnimationFrame(function(){try{unit.scrollIntoView({block:'nearest',behavior:'smooth'});}catch(err){}});
     196    }
     197
     198    cards.forEach(function(card){
     199      var head=card.querySelector(':scope > .itdna-card-head');
     200      if(!head)return;
     201      if(card.getAttribute('data-itdna-accordion-ready')!=='1'){
     202        card.setAttribute('data-itdna-accordion-ready','1');
     203        card.classList.add('itdna-accordion-card');
     204        head.setAttribute('role','button');head.setAttribute('tabindex','0');head.classList.add('itdna-accordion-head');
     205        var indicator=document.createElement('span');indicator.className='itdna-accordion-indicator';indicator.setAttribute('aria-hidden','true');head.appendChild(indicator);
     206        head.addEventListener('click',function(e){if(e.target&&e.target.closest('a,button,input,select,textarea,label'))return;toggleUnit(card,'card');});
     207        head.addEventListener('keydown',function(e){if(e.key==='Enter'||e.key===' '){e.preventDefault();toggleUnit(card,'card');}});
     208      }
     209      setCard(card,false);
     210    });
     211
     212    categories.forEach(function(cat){
     213      var trigger=cat.querySelector(':scope > .itdna-option-category-trigger');
     214      if(!trigger)return;
     215      if(cat.getAttribute('data-itdna-category-ready')!=='1'){
     216        cat.setAttribute('data-itdna-category-ready','1');
     217        trigger.addEventListener('click',function(){toggleUnit(cat,'category');});
     218      }
     219      setCategory(cat,false);
     220    });
     221
     222    // A page may nominate one primary section to be visible immediately.
     223    // Opening any other section closes it; once closed it behaves like every
     224    // other accordion and shows the + affordance until the user reopens it.
     225    // On Workers Save/Test/Run return to the dedicated tab, expand the
     226    // Workers accordion so its notice and fields remain visible.
     227    var r2Return=tab==='turbo10x' && window.location.hash==='#itdna-turbo-10x-duper-speed'
     228      ? root.querySelector('#itdna-turbo-10x-duper-speed.itdna-card') : null;
     229    var defaultOpen=r2Return || (tab==='dashboard' ? (cards.length?cards[0]:null) : root.querySelector('.itdna-card.itdna-default-open, .itdna-option-category.itdna-default-open'));
     230    if(defaultOpen){
     231      closeEverything(defaultOpen);
     232      if(defaultOpen.classList.contains('itdna-card'))setCard(defaultOpen,true);
     233      else setCategory(defaultOpen,true);
     234    }
     235  }
     236
     237  itdnaBindCategoryAccordions(viewMain);
     238
     239  /*
     240   * Live cache dashboard: lightweight admin-only polling. This intentionally
     241   * uses AJAX instead of WebSockets so it works on ordinary shared hosting.
     242   * It pauses when the admin tab is hidden and never touches public requests.
     243   */
     244  /*
     245   * Intelligent v2.5 optimizer. Each stage is one authenticated AJAX request;
     246   * this makes progress visible and prevents a single long admin request from
     247   * attempting every optimization at once.
     248   */
     249  var autoRoot=viewMain.querySelector('[data-itdna-auto-engine]');
     250  if(autoRoot && window.ITDNA_TC_LIVE && ITDNA_TC_LIVE.ajaxUrl && ITDNA_TC_LIVE.autoNonce){
     251    var autoJobId='';
     252    var autoBusy=false;
     253    var autoTimer=null;
     254    var autoNextDelay=10000;
     255    var autoStart=autoRoot.querySelector('[data-itdna-auto-start]');
     256    var autoRollback=autoRoot.querySelector('[data-itdna-auto-rollback]');
     257    var autoStatus=autoRoot.querySelector('[data-itdna-auto-status]');
     258    var autoSite=autoRoot.querySelector('[data-itdna-auto-site]');
     259    var autoProfile=autoRoot.querySelector('[data-itdna-auto-profile]');
     260    var autoRisk=autoRoot.querySelector('[data-itdna-auto-risk]');
     261    var autoBar=autoRoot.querySelector('[data-itdna-auto-progress]');
     262    var autoProgressText=autoRoot.querySelector('[data-itdna-auto-progress-text]');
     263    var autoSteps=autoRoot.querySelector('[data-itdna-auto-steps]');
     264    var autoResults=autoRoot.querySelector('[data-itdna-auto-results]');
     265    var autoChoice=document.querySelector('[data-itdna-auto-choice]');
     266    var autoChoiceButtons=autoChoice?autoChoice.querySelectorAll('[data-itdna-auto-mode]'):[];
     267    var autoChoiceClose=autoChoice?autoChoice.querySelectorAll('[data-itdna-auto-choice-close]'):[];
     268
     269    function openAutoChoice(){if(!autoChoice)return;autoChoice.hidden=false;document.body.classList.add('itdna-modal-open');}
     270    function closeAutoChoice(){if(!autoChoice)return;autoChoice.hidden=true;document.body.classList.remove('itdna-modal-open');}
     271    function startAutoMode(mode){
     272      if(autoBusy)return;
     273      closeAutoChoice(); autoStart.disabled=true; autoSetStatus(mode==='aggressive'?'Starting Max Load…':'Starting Hosting-Aware…');
     274      if(autoProgressText)autoProgressText.textContent=mode==='aggressive'?'Preparing the Aggressive Max Load plan with safety guards…':'Fresh-detecting hosting resources and preparing the recommended plan…';
     275      autoPost('itdna_tc_auto_start',{mode:mode}).then(function(d){autoJobId=d.id||'';autoRender(d);autoPoll();}).catch(function(e){autoStart.disabled=false;autoSetStatus('Error');if(autoProgressText)autoProgressText.textContent=e.message||'Could not start Auto Optimize.';});
     276    }
     277
     278    function autoPost(action,extra){
     279      var body=new URLSearchParams(); body.set('action',action); body.set('nonce',ITDNA_TC_LIVE.autoNonce||'');
     280      Object.keys(extra||{}).forEach(function(k){body.set(k,extra[k]);});
     281      return fetch(ITDNA_TC_LIVE.ajaxUrl,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'},body:body.toString(),cache:'no-store'}).then(function(r){if(!r.ok)throw new Error('HTTP '+r.status);return r.json();}).then(function(j){if(!j||!j.success)throw new Error((j&&j.data&&j.data.message)||'Auto optimizer request failed');return j.data;});
     282    }
     283    function autoSetStatus(text){if(autoStatus)autoStatus.textContent=text;}
     284    function autoRender(d){
     285      if(!d)return;
     286      autoJobId=d.id||autoJobId;
     287      var serverDelay=parseInt(d.next_delay_ms||0,10);
     288      if(serverDelay>0)autoNextDelay=Math.max(1000,Math.min(120000,serverDelay));
     289      if(autoSite&&d.site_type)autoSite.textContent=d.site_type;
     290      if(autoProfile&&d.profile)autoProfile.textContent=d.profile.charAt(0).toUpperCase()+d.profile.slice(1);
     291      if(autoRisk&&d.risk_score!==null&&d.risk_score!==undefined&&d.confidence!==null&&d.confidence!==undefined&&Number.isFinite(Number(d.risk_score))&&Number.isFinite(Number(d.confidence)))autoRisk.textContent=Number(d.risk_score)+'/100 · '+Number(d.confidence)+'%';
     292      if(autoStart)autoStart.disabled=d.status==='running';
     293      if(autoRollback)autoRollback.disabled=!d.id || d.status==='idle' || d.status==='rolled_back' || d.status==='rollback_failed';
     294      var steps=d.steps||[], done=0, current=-1;
     295      steps.forEach(function(st,i){if(st.status==='done'||st.status==='skipped')done++;if(st.status==='running')current=i;});
     296      var pct=steps.length?Math.round((done/steps.length)*100):0;
     297      if(d.status==='complete')pct=100;
     298      if(autoBar)autoBar.style.width=pct+'%';
     299      if(autoProgressText){
     300        if(d.status==='running'&&d.pause_reason)autoProgressText.textContent=String(d.pause_reason)+' Next safe check in about '+Math.max(1,Math.round(autoNextDelay/1000))+'s.';
     301        else if(d.status==='running')autoProgressText.textContent='Step '+Math.min((d.cursor||0)+1,steps.length)+' of '+steps.length+' · '+(current>=0?(steps[current].label||'working…'):'waiting for the next server-safe stage…')+' · next stage paced by server load';
     302        else if(d.status==='complete')autoProgressText.textContent='Complete · all safe stages finished and verified.';
     303        else if(d.status==='rolled_back')autoProgressText.textContent=(d.rollback||{}).status==='verified'?'Rollback VERIFIED · '+String((d.rollback||{}).matched||0)+' settings match the saved snapshot.':'Rollback reported · saved settings comparison NOT VERIFIED (older report).';
     304        else if(d.status==='rollback_failed')autoProgressText.textContent='ROLLBACK NOT VERIFIED · inspect the reported mismatch before doing anything else.';
     305        else autoProgressText.textContent='Ready. Nothing changes until you press Auto Optimize.';
     306      }
     307      if(autoSteps){
     308        autoSteps.innerHTML='';
     309        steps.forEach(function(st,i){
     310          var row=document.createElement('div'); row.className='itdna-v20-step '+(st.status||'pending');
     311          var icon=document.createElement('span'); icon.className='itdna-v20-step-icon'; icon.textContent=st.status==='done'?'✓':(st.status==='running'?'…':(st.status==='failed'?'!':(st.status==='skipped'?'–':'○')));
     312          var wrap=document.createElement('div'); var strong=document.createElement('strong'); strong.textContent=st.label||('Step '+(i+1)); var small=document.createElement('small'); small.textContent=st.detail||''; wrap.appendChild(strong);wrap.appendChild(small);row.appendChild(icon);row.appendChild(wrap);autoSteps.appendChild(row);
     313        });
     314      }
     315      if(autoResults){
     316        var html='';
     317        if((d.changes||[]).length)html+='<div><strong>'+(d.status==='rolled_back'||d.status==='rollback_failed'?'Attempted before rollback':'Applied')+'</strong><span>'+d.changes.length+' change item(s)</span></div>';
     318        if((d.skipped||[]).length)html+='<div><strong>Skipped safely</strong><span>'+d.skipped.length+' item(s)</span></div>';
     319        if((d.external||[]).length)html+='<div><strong>External integrations</strong><span>'+d.external.length+' item(s)</span></div>';
     320        if((d.verification||{}).message)html+='<div><strong>Verification</strong><span>'+String(d.verification.message).replace(/[<>&]/g,function(c){return {'<':'&lt;','>':'&gt;','&':'&amp;'}[c];})+'</span></div>';
     321        if((d.rollback||{}).status)html+='<div><strong>Rollback</strong><span>'+String(d.rollback.status).toUpperCase()+' · '+String(d.rollback.reason||'').replace(/[<>&]/g,function(c){return {'<':'&lt;','>':'&gt;','&':'&amp;'}[c];})+'</span></div>';
     322        autoResults.innerHTML=html;
     323      }
     324      if(d.status==='complete')autoSetStatus('Completed ✓');
     325      else if(d.status==='rolled_back')autoSetStatus((d.rollback||{}).status==='verified'?'Rollback verified ✓':'Rolled back · NOT VERIFIED');
     326      else if(d.status==='rollback_failed')autoSetStatus('Rollback NOT VERIFIED');
     327      else if(d.status==='running')autoSetStatus('Running…');
     328    }
     329    function autoPoll(){
     330      if(!alive()||autoBusy||!autoJobId)return;
     331      autoBusy=true;
     332      autoPost('itdna_tc_auto_step',{job_id:autoJobId}).then(function(d){
     333        autoRender(d);
     334        if(d.status==='running'){autoTimer=window.setTimeout(autoPoll,Math.max(1000,autoNextDelay));}
     335      }).catch(function(e){
     336        autoSetStatus('Error');
     337        if(autoProgressText)autoProgressText.textContent=e.message||'Auto optimizer request failed.';
     338      }).finally(function(){autoBusy=false;});
     339    }
     340    if(autoStart)autoStart.addEventListener('click',function(){if(autoBusy)return;openAutoChoice();});
     341    if(autoChoiceButtons&&autoChoiceButtons.length)autoChoiceButtons.forEach(function(btn){btn.addEventListener('click',function(){startAutoMode(btn.getAttribute('data-itdna-auto-mode')==='aggressive'?'aggressive':'server_aware');});});
     342    if(autoChoiceClose&&autoChoiceClose.length)autoChoiceClose.forEach(function(btn){btn.addEventListener('click',closeAutoChoice);});
     343    document.addEventListener('keydown',function(e){if(!alive())return;if(e.key==='Escape'&&autoChoice&&!autoChoice.hidden)closeAutoChoice();});
     344    if(autoRollback)autoRollback.addEventListener('click',function(){
     345      var rollbackMessage=autoJobId
     346        ? 'Rollback this Intelligent Auto Optimize run? Current Turbo Cache settings from that run will be restored.'
     347        : 'Rollback the last Intelligent Auto Optimize run? Current Turbo Cache settings from that run will be restored.';
     348      if(!window.confirm(rollbackMessage))return;
     349      autoRollback.disabled=true;autoSetStatus('Rolling back…');
     350      autoPost('itdna_tc_auto_rollback',{}).then(function(d){autoRender(d);}).catch(function(e){autoRollback.disabled=false;autoSetStatus('Rollback error');if(autoProgressText)autoProgressText.textContent=e.message||'Rollback failed.';});
     351    });
     352    var existing=autoRoot.getAttribute('data-status');
     353    if(existing==='running'){
     354      autoJobId=autoRoot.getAttribute('data-job-id')||'';
     355      var existingDelay=parseInt(autoRoot.getAttribute('data-next-delay-ms')||'0',10);
     356      if(existingDelay>0)autoNextDelay=Math.max(1000,Math.min(120000,existingDelay));
     357      if(autoJobId){autoTimer=window.setTimeout(autoPoll,Math.max(1000,autoNextDelay));}
     358    }
     359  }
     360
     361  /*
     362   * Performance Doctor one-click workflow.
     363   * Scan and fix are separate authenticated AJAX requests with a browser-side
     364   * five-second cooldown between them. PHP is never kept sleeping/blocked.
     365   */
     366  var perfRoot=viewMain.querySelector('[data-itdna-performance-flow]');
     367  if(perfRoot && window.ITDNA_TC_LIVE && ITDNA_TC_LIVE.ajaxUrl && ITDNA_TC_LIVE.performanceNonce){
     368    var perfButton=perfRoot.querySelector('[data-itdna-performance-run]');
     369    var perfStatus=perfRoot.querySelector('[data-itdna-performance-status]');
     370    var perfProgress=document.querySelector('[data-itdna-performance-progress]');
     371    var perfBar=perfProgress?perfProgress.querySelector('[data-itdna-performance-bar]'):null;
     372    var perfBusy=false;
     373    function perfSet(text,pct){
     374      if(perfStatus)perfStatus.textContent=text;
     375      if(perfProgress){perfProgress.hidden=false;}
     376      if(perfBar&&typeof pct==='number')perfBar.style.width=Math.max(0,Math.min(100,pct))+'%';
     377    }
     378    function perfPost(action){
     379      var body=new URLSearchParams();
     380      body.set('action',action);body.set('nonce',ITDNA_TC_LIVE.performanceNonce||'');
     381      return fetch(ITDNA_TC_LIVE.ajaxUrl,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'},body:body.toString(),cache:'no-store'})
     382        .then(function(r){return r.json().catch(function(){throw new Error('Invalid server response.');}).then(function(j){if(!r.ok||!j||!j.success)throw new Error((j&&j.data&&j.data.message)||('HTTP '+r.status));return j.data;});});
     383    }
     384    function perfCountdown(seconds,label,startPct,spanPct){
     385      return new Promise(function(resolve){
     386        var left=seconds,base=typeof startPct==='number'?startPct:35,span=typeof spanPct==='number'?spanPct:20;
     387        function tick(){
     388          if(left<=0){resolve();return;}
     389          perfSet((label||'Safe cooldown')+' '+left+'s…',base+Math.round(((seconds-left)/seconds)*span));
     390          left--;window.setTimeout(tick,1000);
    10391        }
    11         return null;
    12     }
    13 
    14     function updateMetric(label, value, note) {
    15         var card = findMetric(label);
    16         if (!card) return;
    17         var strong = card.querySelector('strong');
    18         var small = card.querySelector('small');
    19         if (strong && strong.textContent !== String(value)) {
    20             strong.textContent = String(value);
    21             strong.classList.add('itdna-live-flash');
    22             window.setTimeout(function () { strong.classList.remove('itdna-live-flash'); }, 500);
     392        tick();
     393      });
     394    }
     395    if(perfButton)perfButton.addEventListener('click',function(){
     396      if(perfBusy)return;
     397      perfBusy=true;perfButton.disabled=true;
     398      perfSet('Step 1/3 · Running full performance scan…',10);
     399      perfPost('itdna_tc_performance_scan')
     400        .then(function(scan){
     401          perfSet('Initial measured scan complete · preparing safe fix…',35);
     402          return perfCountdown(5,'Initial scan complete · safe cooldown before frontend fix',35,20);
     403        })
     404        .then(function(){
     405          perfSet('Step 2/3 · Applying bounded Frontend Safe Fix…',60);
     406          return perfPost('itdna_tc_performance_fix');
     407        })
     408        .then(function(fixed){
     409          if(fixed&&Number(fixed.css_pending||0)===1){
     410            perfSet('Smart CSS repair queued safely · waiting 10s for the governed one-page build…',78);
     411            return perfCountdown(10,'Smart CSS repair queued safely · waiting for the governed one-page build',78,12).then(function(){
     412              perfSet('Step 3/3 · Re-checking the homepage after Smart CSS repair…',92);
     413              return perfPost('itdna_tc_performance_scan').catch(function(){return null;});
     414            }).then(function(){
     415              perfSet('Verification complete ✓ · refreshing measured results…',100);
     416              window.setTimeout(function(){window.location.reload();},900);
     417            });
     418          }
     419          perfSet('Step 3/3 · Verification complete ✓ · refreshing measured results…',100);
     420          window.setTimeout(function(){window.location.reload();},900);
     421        })
     422        .catch(function(e){
     423          perfSet('Stopped safely: '+(e&&e.message?e.message:'Performance workflow failed.'),0);
     424          perfBusy=false;perfButton.disabled=false;
     425        });
     426    });
     427  }
     428
     429  /*
     430   * Zero-touch Easy Auto Setup dashboard. Polling advances at most one due stage;
     431   * WP-Cron is the fallback when the dashboard is closed. No page reload or repeated
     432   * user clicks are required.
     433   */
     434  var easyRoot=viewMain.querySelector('[data-itdna-easy-setup]');
     435  if(easyRoot && window.ITDNA_TC_LIVE && ITDNA_TC_LIVE.ajaxUrl && ITDNA_TC_LIVE.easySetupNonce){
     436    var easyTimer=null,easyBusy=false,easyState={phase:easyRoot.getAttribute('data-phase')||'',target_remaining:0,status:easyRoot.getAttribute('data-status')||''},easyPollErrors=0,easyPendingError='';
     437    var easyStart=easyRoot.querySelector('[data-itdna-easy-start]');
     438    var easyBadge=easyRoot.querySelector('[data-itdna-easy-badge]');
     439    var easyBar=easyRoot.querySelector('[data-itdna-easy-bar]');
     440    var easyPhase=easyRoot.querySelector('[data-itdna-easy-phase]');
     441    var easyPct=easyRoot.querySelector('[data-itdna-easy-progress-text]');
     442    var easyMsg=easyRoot.querySelector('[data-itdna-easy-message]');
     443    var easyVerdict=easyRoot.querySelector('[data-itdna-easy-verdict]');
     444    var easyLimit=easyRoot.querySelector('[data-itdna-easy-limitations]');
     445    var easyIssues=easyRoot.querySelector('[data-itdna-easy-issues]');
     446    function easyPost(action,extra){
     447      var b=new URLSearchParams();b.set('action',action);b.set('nonce',ITDNA_TC_LIVE.easySetupNonce||'');
     448      Object.keys(extra||{}).forEach(function(k){b.set(k,String(extra[k]));});
     449      return fetch(ITDNA_TC_LIVE.ajaxUrl,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'},body:b.toString(),cache:'no-store'})
     450        .then(function(r){return r.json().catch(function(){throw new Error('Invalid setup response.');}).then(function(j){if(!r.ok||!j||!j.success)throw new Error((j&&j.data&&j.data.message)||('HTTP '+r.status));return j.data;});});
     451    }
     452    function easyNum(v){return (v===null||typeof v==='undefined'||v==='')?'—':new Intl.NumberFormat().format(Number(v)||0);}
     453    function easyMs(v){return Number(v)>0?easyNum(v)+' ms':'—';}
     454    function easyBytes(v){var n=Number(v)||0;if(n<=0)return '—';var u=['B','KB','MB','GB'],i=0;while(n>=1024&&i<u.length-1){n/=1024;i++;}return (i===0?Math.round(n):n.toFixed(n>=10?0:1))+' '+u[i];}
     455    function easyTextMetric(obj,key){
     456      if(!obj||!obj.ok)return '—';
     457      if(key==='response_ms')return easyMs(obj.response_ms);
     458      if(key==='initial_asset_bytes')return easyBytes(obj.initial_asset_bytes);
     459      if(key==='cache')return obj.cache||'NO-HEADER';
     460      if(key==='benchmark_profile_label')return obj.benchmark_profile_label||'—';
     461      if(key==='benchmark_requests')return easyNum(obj.benchmark_requests);
     462      return easyNum(obj[key]);
     463    }
     464    function easyLabel(status){
     465      if(status==='running')return 'RUNNING AUTOMATICALLY';
     466      if(status==='complete')return 'COMPLETE';
     467      if(status==='attention')return 'NEEDS ATTENTION';
     468      if(status==='superseded')return 'STOPPED BY MANUAL ACTION';
     469      if(status==='waiting')return 'WAITING SAFELY';
     470      return 'READY';
     471    }
     472    function easyRender(d){
     473      d=d||{};var st=d.status||'ready',pct=Math.max(0,Math.min(100,Number(d.progress)||0));
     474      easyState={phase:d.phase||'ready',target_remaining:Number(d.target_remaining)||0,status:st};easyPollErrors=0;
     475      easyRoot.setAttribute('data-status',st);
     476      if(easyBadge)easyBadge.textContent=easyLabel(st);
     477      if(easyBar)easyBar.style.width=pct+'%';
     478      if(easyPct)easyPct.textContent='Workflow '+Math.round(pct)+'%';
     479      if(easyPhase)easyPhase.textContent=String(d.phase||'ready').replace(/_/g,' ').replace(/\b\w/g,function(c){return c.toUpperCase();});
     480      if(easyMsg){var msg=d.message||'';if(st==='running'&&easyState.phase==='settling'&&easyState.target_remaining>0){var sec=Math.max(0,Math.round(easyState.target_remaining)),min=Math.floor(sec/60);msg+=' Final check in '+min+'m '+(sec%60)+'s.';}easyMsg.textContent=msg;}
     481      var before=d.baseline||{},current=d.current||{};
     482      easyRoot.querySelectorAll('[data-itdna-easy-before]').forEach(function(el){el.textContent=easyTextMetric(before,el.getAttribute('data-itdna-easy-before'));});
     483      easyRoot.querySelectorAll('[data-itdna-easy-current]').forEach(function(el){el.textContent=easyTextMetric(current,el.getAttribute('data-itdna-easy-current'));});
     484      var cmp=d.comparison||{},out=d.outcome||{};
     485      var outcomeMap={setup:(st==='complete'?'COMPLETE':Math.round(pct)+'%'),timing:((Number(current.response_ms)||0)>0 ? ((String(current.cache).toUpperCase()==='HIT' && Number(current.response_ms)<=100)?'EXCELLENT':(Number(current.response_ms)<=250?'FAST':(Number(current.response_ms)<=500?'OK':'NEEDS WORK'))) + ' · ' + easyNum(current.response_ms) + ' ms' : (st==='complete'?'Measurement unavailable':'Pending final measurement')),applied:easyNum(out.applied_count||0),verified:easyNum(out.verified_count||0),skipped:easyNum(out.skipped_count||0),limiting:easyNum(out.limiting_count||0)};
     486      easyRoot.querySelectorAll('[data-itdna-easy-outcome]').forEach(function(el){var k=el.getAttribute('data-itdna-easy-outcome');if(Object.prototype.hasOwnProperty.call(outcomeMap,k))el.textContent=outcomeMap[k];});
     487      var timingChange=easyRoot.querySelector('[data-itdna-easy-timing-change]');
     488      if(timingChange)timingChange.textContent=out.timing_label||(st==='complete'?'No verified speed gain':'Pending final measurement');
     489      var delivery=d.delivery||{}, deliveryEl=easyRoot.querySelector('[data-itdna-easy-delivery]'), deliveryNote=easyRoot.querySelector('[data-itdna-easy-delivery-note]');
     490      if(deliveryEl)deliveryEl.textContent=delivery.summary||'Unavailable';
     491      if(deliveryNote)deliveryNote.textContent=delivery.note||'';
     492      if(easyVerdict){
     493        easyVerdict.hidden=!cmp.message;easyVerdict.textContent=cmp.message||'';
     494        easyVerdict.classList.remove('ok','error','warn','info');
     495        easyVerdict.classList.add(cmp.verdict==='improved'?'ok':(cmp.verdict==='slower'?'error':(cmp.verdict==='needs_review'?'warn':'info')));
     496      }
     497      var appliedRows=(Array.isArray(out.applied)?out.applied:[]).concat(Array.isArray(out.verified)?out.verified:[]).filter(function(v,i,a){return a.indexOf(v)===i;});
     498      var skippedRows=Array.isArray(out.skipped)?out.skipped:[];
     499      var resultDetails=easyRoot.querySelector('[data-itdna-easy-result-details]'), appliedList=easyRoot.querySelector('[data-itdna-easy-applied-list]'), skippedList=easyRoot.querySelector('[data-itdna-easy-skipped-list]');
     500      function easyList(el,rows){if(!el)return;el.innerHTML='';rows.slice(0,8).forEach(function(v){var r=document.createElement('div');r.textContent='• '+String(v);el.appendChild(r);});}
     501      easyList(appliedList,appliedRows);easyList(skippedList,skippedRows);if(resultDetails)resultDetails.hidden=!(appliedRows.length||skippedRows.length);
     502      var issues=Array.isArray(d.blockers)?d.blockers:[];
     503      if(easyLimit)easyLimit.hidden=!issues.length;
     504      if(easyIssues){easyIssues.innerHTML='';issues.slice(0,8).forEach(function(it){var row=document.createElement('div');var b=document.createElement('b');b.textContent=(it.label||'Attention')+': ';row.appendChild(document.createTextNode('• '));row.appendChild(b);row.appendChild(document.createTextNode(it.detail||''));easyIssues.appendChild(row);});}
     505      if(easyStart){easyStart.hidden=(st==='running');easyStart.disabled=false;easyStart.textContent=st==='complete'?'Run Easy Auto Setup Again':'Run Easy Auto Setup';}
     506      if(easyTimer){window.clearTimeout(easyTimer);easyTimer=null;}
     507      if(st==='running'){var wait=(easyState.phase==='settling'?30000:10000);if(easyState.phase==='settling'&&easyState.target_remaining>90)wait=60000;easyTimer=window.setTimeout(easyPoll,wait);}
     508    }
     509    function easyPoll(){
     510      if(!alive()||easyBusy)return;easyBusy=true;
     511      var settling=easyState.phase==='settling',due=Number(easyState.target_remaining||0)<=3;
     512      // While cache is merely settling, polling is read-only. WP-Cron owns the wait;
     513      // the browser advances only once the real final measurement is due. This avoids
     514      // hammering admin-ajax/WAF rules every 10 seconds for ~10 minutes.
     515      var advance=(!settling||due)?1:0;
     516      var pending=easyPendingError;
     517      easyPost('itdna_tc_easy_setup_status',{advance:advance,client_error:pending}).then(function(d){if(pending&&easyPendingError===pending)easyPendingError='';easyRender(d);}).catch(function(e){
     518        easyPollErrors++;
     519        easyPendingError=String((e&&e.message)||'request error').slice(0,180);
     520        if(easyMsg)easyMsg.textContent='Live setup status is temporarily unavailable ('+easyPendingError+'). Setup continues safely in WP-Cron; retrying automatically.';
     521        easyTimer=window.setTimeout(easyPoll,Math.min(120000,30000+(easyPollErrors*15000)));
     522      }).finally(function(){easyBusy=false;});
     523    }
     524    function easyStartFallback(reason){
     525      var url=(ITDNA_TC_LIVE&&ITDNA_TC_LIVE.adminPostUrl)||'';
     526      if(!url)return false;
     527      if(easyMsg)easyMsg.textContent='admin-ajax was blocked ('+String(reason||'request blocked')+'). Retrying once through normal WordPress admin-post…';
     528      var f=document.createElement('form');f.method='POST';f.action=url;f.style.display='none';
     529      [['action','itdna_tc_easy_setup_start_fallback'],['nonce',ITDNA_TC_LIVE.easySetupNonce||'']].forEach(function(pair){var i=document.createElement('input');i.type='hidden';i.name=pair[0];i.value=pair[1];f.appendChild(i);});
     530      document.body.appendChild(f);f.submit();return true;
     531    }
     532    if(easyStart)easyStart.addEventListener('click',function(){
     533      if(easyBusy)return;easyBusy=true;easyStart.disabled=true;if(easyMsg)easyMsg.textContent='Starting real Before Auto Setup measurement…';
     534      easyPost('itdna_tc_easy_setup_start',{}).then(easyRender).catch(function(e){
     535        var msg=String((e&&e.message)||'Could not start Easy Auto Setup.');
     536        if(/403|unauthori[sz]ed|invalid setup response/i.test(msg)&&easyStartFallback(msg))return;
     537        easyStart.disabled=false;if(easyMsg)easyMsg.textContent=msg;
     538      }).finally(function(){easyBusy=false;});
     539    });
     540    if((easyRoot.getAttribute('data-status')||'')==='running'){easyTimer=window.setTimeout(easyPoll,1200);}
     541  }
     542
     543  var optimizerPanel=viewMain.querySelector('[data-itdna-optimizer-live]');
     544  if(optimizerPanel && window.ITDNA_TC_LIVE && ITDNA_TC_LIVE.ajaxUrl){
     545    var optBusy=false,optTimer=null,optInterval=10000,optStopped=false,optStarted=false,optTab=optimizerPanel.getAttribute('data-itdna-optimizer-live')==='images'?'images':'optimization';
     546    function optFmt(n){try{return new Intl.NumberFormat().format(Number(n)||0);}catch(e){return String(Number(n)||0);}}
     547    function optSet(k,v){document.querySelectorAll('[data-itdna-opt-value="'+k+'"]').forEach(function(el){var t=String(v);if(el.textContent!==t){el.textContent=t;el.classList.remove('itdna-live-flash');void el.offsetWidth;el.classList.add('itdna-live-flash');}var stat=el.closest('[data-itdna-zero-sensitive="1"]');if(stat){stat.classList.remove('is-pending');var n=Number(String(v).replace(/[^0-9.-]/g,''));stat.classList.toggle('is-zero',!isNaN(n)&&n===0);}if(k==='integrity_css'||k==='integrity_js'){var badge=el.closest('.itdna-integrity-badge');if(badge){var state=String(v).toUpperCase(),pass=state==='PASS',fail=state==='FAIL';badge.classList.toggle('is-pass',pass);badge.classList.toggle('is-fail',fail);badge.classList.toggle('is-pending',!pass&&!fail);}}});}
     548    function optHas(o,k){return !!o&&Object.prototype.hasOwnProperty.call(o,k);}
     549    function optMetric(outKey,o,srcKey){if(optHas(o,srcKey))optSet(outKey,optFmt(o[srcKey]));}
     550    function optIntegrity(rp,kind){var ik='integrity_'+kind;if(optHas(rp,ik))return rp[ik]?'PASS':'FAIL';var dk='detected_'+kind,lk='local_'+kind,ek='eligible_'+kind,rk='reused_'+kind,sk='local_skipped_'+kind,xk='external_'+kind;if(!optHas(rp,dk)&&!optHas(rp,lk))return 'PENDING';var d=Number(rp[dk])||0,l=Number(rp[lk])||0,e=Number(rp[ek])||0,r=Number(rp[rk])||0,s=Number(rp[sk])||0,x=Number(rp[xk])||0;return (l===e+r+s&&d===l+x)?'PASS':'FAIL';}
     551    function optPoll(){
     552      if(!alive()||optStopped)return;
     553      if(document.hidden){optTimer=window.setTimeout(optPoll,Math.max(30000,optInterval*2));return;}
     554      if(optBusy){optTimer=window.setTimeout(optPoll,optInterval);return;}
     555      optBusy=true;
     556      var b=new URLSearchParams();b.set('action','itdna_tc_optimizer_live');b.set('nonce',ITDNA_TC_LIVE.optimizerNonce||'');b.set('tab',optTab);
     557      fetch(ITDNA_TC_LIVE.ajaxUrl,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'},body:b.toString(),cache:'no-store'})
     558        .then(function(r){if(!r.ok)throw new Error('HTTP '+r.status);return r.json();})
     559        .then(function(j){
     560          if(!j||!j.success||!j.data)throw new Error('Live optimizer unavailable');
     561          if(j.data.paused){optStopped=true;window.clearTimeout(optTimer);return;}
     562          var gov=j.data.governor||{};
     563          if(gov.admin_poll_ms){optInterval=Math.max(10000,Math.min(60000,Number(gov.admin_poll_ms)||10000));}
     564          if(gov.score!==undefined)optSet('governor_pressure',Math.round(Number(gov.score)||0)+'%');
     565          if(gov.level)optSet('governor_level',gov.level);
     566          if(gov.capacity)optSet('governor_capacity',gov.capacity);
     567          if(gov.image_batch!==undefined)optSet('governor_image_batch',gov.image_batch);
     568          if(gov.preload_batch!==undefined)optSet('governor_preload_batch',gov.preload_batch);
     569          if(gov.admin_poll_ms)optSet('governor_admin_poll',Math.round(Number(gov.admin_poll_ms)/1000)+'s');
     570          if(j.data.images){
     571            var d=j.data.images,s=d.stats||{},sc=d.scan||{},w=d.worker||{};
     572            optSet('webp',optFmt(s.webp));optSet('avif',optFmt(s.avif));optSet('processed',optFmt(s.processed));optSet('queue',optFmt(d.queue));optSet('scan',sc.active?'Running':'Idle');optSet('scanned',optFmt(sc.scanned));
     573            var p=document.querySelector('[data-itdna-image-worker]');
     574            if(p)p.innerHTML='<strong>Last worker:</strong> '+String(w.message||'Waiting for the next background batch.').replace(/[<>&]/g,function(c){return {'<':'&lt;','>':'&gt;','&':'&amp;'}[c];});
     575          }
     576          if(j.data.assets){
     577            var a=j.data.assets||{},rp=a.build_report||{};
     578            optMetric('detected_css',rp,'detected_css');optMetric('local_css',rp,'local_css');optMetric('external_css',rp,'external_css');optMetric('eligible_css',rp,'eligible_css');optMetric('built_css',rp,'optimized_css');optMetric('reused_css',rp,'reused_css');optMetric('local_skipped_css',rp,'local_skipped_css');optSet('integrity_css',optIntegrity(rp,'css'));optSet('css_assets',optFmt(a.css_assets));
     579            optMetric('detected_js',rp,'detected_js');optMetric('local_js',rp,'local_js');optMetric('external_js',rp,'external_js');optMetric('eligible_js',rp,'eligible_js');optMetric('built_js',rp,'optimized_js');optMetric('reused_js',rp,'reused_js');optMetric('local_skipped_js',rp,'local_skipped_js');optSet('integrity_js',optIntegrity(rp,'js'));optSet('js_assets',optFmt(a.js_assets));optSet('assets',optFmt(a.assets));
     580            var bytes=Number(a.asset_bytes)||0,sz=bytes<1024?bytes+' B':(bytes<1048576?(bytes/1024).toFixed(1)+' KB':(bytes/1048576).toFixed(1)+' MB');optSet('asset_size',sz);
     581            var bs=document.querySelector('[data-itdna-asset-build-status]');
     582            if(bs&&rp.message){bs.textContent='Build status: '+String(rp.message);}
     583          }
     584          if(!gov.admin_poll_ms)optInterval=10000;
     585        })
     586        .catch(function(){optInterval=Math.min(30000,Math.round(optInterval*1.6));})
     587        .finally(function(){optBusy=false;if(!optStopped)optTimer=window.setTimeout(optPoll,optInterval);});
     588    }
     589    function optStart(){if(optStarted||optStopped)return;optStarted=true;optPoll();}
     590    // The asset/image live report can sit far below the settings controls. Do not wake
     591    // admin-ajax merely because the tab opened; start only when the report approaches
     592    // the viewport. This lowers wp-admin load and avoids generic host/WAF error toasts.
     593    if('IntersectionObserver' in window){
     594      var optObserver=new IntersectionObserver(function(entries){
     595        for(var oi=0;oi<entries.length;oi++){if(entries[oi].isIntersecting){optObserver.disconnect();optStart();break;}}
     596      },{root:null,rootMargin:'700px 0px',threshold:0});
     597      optObserver.observe(optimizerPanel);
     598    }else{
     599      window.setTimeout(optStart,2500);
     600    }
     601  }
     602
     603  var liveCards=viewMain.querySelectorAll('[data-itdna-live-metric]');
     604  var liveStatus=viewMain.querySelector('[data-itdna-live-status]');
     605  if(!liveCards.length || !window.ITDNA_TC_LIVE || !ITDNA_TC_LIVE.ajaxUrl){return;}
     606
     607  var liveBaseInterval=Math.max(10000,parseInt(ITDNA_TC_LIVE.interval,10)||10000);
     608  // Optimization/Image screens already have their own read-only optimizer poller. Keep
     609  // the general live counters live, but do not wake a second PHP AJAX loop every 2s.
     610  if(optimizerPanel){liveBaseInterval=Math.max(10000,liveBaseInterval);}
     611  var timer=null, busy=false, interval=liveBaseInterval;
     612  var maxInterval=Math.max(interval,parseInt(ITDNA_TC_LIVE.maxInterval,10)||60000);
     613  var lastServerTime=0, consecutiveLiveFailures=0;
     614
     615  function setStatus(mode,text){
     616    if(!liveStatus)return;
     617    liveStatus.classList.remove('is-live','is-warn','is-error');
     618    if(mode==='live')liveStatus.classList.add('is-live');
     619    if(mode==='warn')liveStatus.classList.add('is-warn');
     620    if(mode==='error')liveStatus.classList.add('is-error');
     621    var small=liveStatus.querySelector('[data-itdna-live-time]');
     622    if(small)small.textContent=text||'';
     623  }
     624
     625  function formatNumber(n){
     626    try{return new Intl.NumberFormat().format(Number(n)||0);}catch(e){return String(Number(n)||0);}
     627  }
     628
     629  function updateCard(key,value,sub){
     630    document.querySelectorAll('[data-itdna-live-metric="'+CSS.escape(key)+'"]').forEach(function(card){
     631      var v=card.querySelector('[data-itdna-live-value]');
     632      var s=card.querySelector('[data-itdna-live-sub]');
     633      if(v && value!==undefined){
     634        var next=String(value);
     635        if(v.textContent!==next){
     636          v.classList.remove('itdna-live-flash');
     637          void v.offsetWidth;
     638          v.textContent=next;
     639          v.classList.add('itdna-live-flash');
    23640        }
    24         if (small && note) small.textContent = note;
    25     }
    26 
    27     function setLive(state) {
    28         var root = document.querySelector('[data-itdna-live-status]');
    29         if (!root) return;
    30         root.classList.toggle('is-live', !!state);
    31     }
    32 
    33     function refresh() {
    34         var data = new URLSearchParams();
    35         data.append('action', 'itdna_tc_lite_stats');
    36         data.append('nonce', window.itdnaTcLite.nonce);
    37         fetch(window.itdnaTcLite.ajaxUrl, {
    38             method: 'POST',
    39             credentials: 'same-origin',
    40             headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
    41             body: data.toString()
    42         }).then(function (r) { return r.json(); }).then(function (json) {
    43             if (!json || !json.success || !json.data) { setLive(false); return; }
    44             updateMetric('Page Cache', json.data.enabled ? 'ON' : 'OFF', 'Working Lite feature');
    45             updateMetric('GZIP HTML', json.data.gzip ? 'ON' : 'OFF', 'Working Lite feature');
    46             updateMetric('HTML Cleanup', json.data.html_minify ? 'ON' : 'OFF', 'Safe Lite option');
    47             updateMetric('Cached Pages', String(json.data.count || 0), json.data.size || '0 B');
    48             setLive(true);
    49         }).catch(function () { setLive(false); });
    50     }
    51 
    52     refresh();
    53     window.setInterval(refresh, 5000);
     641      }
     642      if(s && sub!==undefined)s.textContent=sub;
     643    });
     644  }
     645
     646  function ageText(ts){
     647    if(!ts)return 'Waiting for traffic';
     648    var sec=Math.max(0,Math.floor(Date.now()/1000)-Number(ts));
     649    if(sec<2)return 'just now';
     650    if(sec<60)return sec+'s ago';
     651    var min=Math.floor(sec/60);return min+'m ago';
     652  }
     653
     654  function schedule(delay){
     655    window.clearTimeout(timer);
     656    if(!alive()||document.hidden)return;
     657    timer=window.setTimeout(poll,delay);
     658  }
     659
     660  function poll(){
     661    if(!alive())return;
     662    if(document.hidden){schedule(5000);return;}
     663    if(busy){schedule(interval);return;}
     664    busy=true;
     665    var body=new URLSearchParams();
     666    body.set('action','itdna_tc_live_stats');
     667    body.set('nonce',ITDNA_TC_LIVE.nonce||'');
     668    fetch(ITDNA_TC_LIVE.ajaxUrl,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'},body:body.toString(),cache:'no-store'})
     669      .then(function(r){if(!r.ok)throw new Error('HTTP '+r.status);return r.json().catch(function(){throw new Error('Invalid server response');});})
     670      .then(function(json){
     671        if(!json || !json.success || !json.data)throw new Error((json&&json.data&&json.data.message)||'Live stats unavailable');
     672        consecutiveLiveFailures=0;
     673        if(json.data.paused){window.clearTimeout(timer);timer=null;setStatus('warn','Reload page to resume live stats');return;}
     674        var d=json.data;
     675        updateCard('cached_pages',formatNumber(d.cached_pages),d.cached_size);
     676        if(Number(d.external_page_cache)>0){
     677          var extOwner=String(d.external_page_cache_owner||'External full-page cache');
     678          updateCard('hit_rate','EXTERNAL',extOwner+' owns full-page cache; IndiaTVDNA does not invent its HIT percentage.');
     679          updateCard('early_hits','STANDBY','IndiaTVDNA early cache is intentionally inactive while '+extOwner+' owns delivery.');
     680          updateCard('stale','LOCAL N/A','External full-page stale delivery is outside IndiaTVDNA local counters.');
     681          updateCard('misses','LOCAL N/A','External-owner misses cannot be inferred from IndiaTVDNA local counters.');
     682        }else{
     683          var hitMeta=formatNumber(d.samples)+' cacheable origin samples';
     684          if(Number(d.origin_samples)>0){hitMeta+=' · '+formatNumber(d.origin_samples)+' total origin samples';}
     685          updateCard('hit_rate',d.hit_rate,hitMeta);
     686          updateCard('early_hits',formatNumber(d.early_hits),'Served before normal WordPress bootstrap');
     687          updateCard('stale',formatNumber(d.stale),'Fast stale-while-revalidate responses');
     688          updateCard('misses',formatNumber(d.misses),'Sampled requests that needed WordPress/rebuild');
     689        }
     690        lastServerTime=Number(d.server_time)||Math.floor(Date.now()/1000);
     691        setStatus('live','Live · updated just now');
     692        var cq=d.central_queue||{};var cqs=cq.status||{};updateCard('queue_pending',formatNumber(cqs.pending||0),String(cqs.status||'idle'));
     693        var tele=d.hosting_telemetry||{};
     694        var speed=viewMain.querySelector('[data-itdna-speed-console]');
     695        if(speed){
     696          function put(attr,value){var el=speed.querySelector('['+attr+']');if(el)el.textContent=value;}
     697          put('data-itdna-load-cpu',tele.cpu_value===null||tele.cpu_value===undefined?'Unavailable':String(tele.cpu_value)+'%');
     698          put('data-itdna-load-cpu-detail',String(tele.cpu_label||'Hosting does not expose CPU measurements'));
     699          put('data-itdna-load-memory',tele.memory_value===null||tele.memory_value===undefined?'Unavailable':String(tele.memory_value)+'%');
     700          put('data-itdna-load-memory-detail',String(tele.memory_label||'Hosting does not expose memory measurements'));
     701          put('data-itdna-load-average',tele.load_avg===null||tele.load_avg===undefined?'Unavailable':String(tele.load_avg));
     702          put('data-itdna-load-average-detail',String(tele.load_label||'1-minute host load (not CPU%)'));
     703          var scoped=tele.scope_verified===true||tele.scope_verified===1;
     704          var accountScoped=tele.account_scope_verified===true||tele.account_scope_verified===1;
     705          var cpu=scoped&&tele.cpu_value!==null&&tele.cpu_value!==undefined?String(tele.cpu_value)+'%':'Unavailable';
     706          var ram=scoped&&tele.memory_value!==null&&tele.memory_value!==undefined?String(tele.memory_value)+'%':'Unavailable';
     707          speed.querySelectorAll('[data-speed-cpu-ram]').forEach(function(el){el.textContent='Scoped CPU '+cpu+' · RAM '+ram+(accountScoped?' · verified hosting account':(scoped?' · container quota; account unverified':' · account unknown; runtime guard active'));});
     708        }
     709        var hg=d.hosting_guard||{};
     710        if(speed&&hg.profile){
     711          var a=speed.querySelector('[data-itdna-host-active]');if(a)a.textContent=String(hg.profile);
     712          var b=speed.querySelector('[data-itdna-host-allowed]');if(b)b.textContent=String(Number(hg.allowed)||1);
     713          var c=speed.querySelector('[data-itdna-host-status]');
     714          if(c)c.textContent=(!hg.enabled?'⚪ Adaptive Speed OFF · Safe · ':(hg.emergency?'🚨 Emergency Safe Mode · ':(hg.verified?'🟢 Verified account resources · ':(hg.safety_mode==='runtime-downshift'?'🟠 Runtime pressure downshift · ':'⚪ CPU/RAM unknown · Runtime guard ready · '))))+
     715            'High load: '+Math.max(Number(hg.high_cpu_for)||0,Number(hg.high_ram_for)||0)+' / 20s · '+String(hg.warning||'');
     716        }
     717        var g=d.governor||{};
     718        var governorPoll=g.admin_poll_ms?Math.max(10000,Math.min(60000,Number(g.admin_poll_ms)||10000)):0;
     719        interval=Math.max(liveBaseInterval,governorPoll||0);
     720      })
     721      .catch(function(err){
     722        consecutiveLiveFailures++;
     723        var raw=String(err&&err.message||'Network failure');
     724        var reason=/HTTP 403/.test(raw)?'Access denied (403) · reload dashboard':
     725          /HTTP (500|502|503|504)/.test(raw)?'Server error · check hosting PHP log':
     726          /Invalid server response/.test(raw)?'Invalid AJAX response · check PHP log':
     727          /Failed to fetch|NetworkError|Network failure/.test(raw)?'Network blocked · check browser/firewall':
     728          raw.substring(0,90);
     729        setStatus(consecutiveLiveFailures>=2?'error':'warn','LIVE unavailable · '+reason);
     730        if(liveStatus)liveStatus.title='Last live polling error: '+raw.substring(0,160);
     731        interval=Math.min(maxInterval,Math.round(interval*1.7));
     732      })
     733      .finally(function(){busy=false;schedule(interval);});
     734  }
     735
     736  document.addEventListener('visibilitychange',function(){
     737    if(!alive())return;
     738    if(document.hidden){window.clearTimeout(timer);timer=null;setStatus('warn','Paused while tab is hidden');}
     739    else{interval=liveBaseInterval;setStatus('warn','Reconnecting…');poll();}
     740  });
     741
     742  poll();
     743
     744}
     745
     746function itdnaRefreshLocalizedState(doc){
     747  try{
     748    var node=doc&&doc.querySelector?doc.querySelector('#itdna-tc-admin-js-extra'):null;
     749    if(!node)return;
     750    var txt=node.textContent||'';
     751    var m=txt.match(/var\s+ITDNA_TC_LIVE\s*=\s*(\{[\s\S]*\})\s*;?\s*$/);
     752    if(m&&m[1])window.ITDNA_TC_LIVE=JSON.parse(m[1]);
     753  }catch(e){}
     754}
     755
     756function itdnaSetActiveNav(tab){
     757  document.querySelectorAll('.itdna-sidebar nav a[href*="page=itdna-turbo-cache"]').forEach(function(a){
     758    try{
     759      var u=new URL(a.href,location.href),t=u.searchParams.get('tab')||'dashboard';
     760      a.classList.toggle('active',t===tab);
     761      if(t===tab)a.setAttribute('aria-current','page');else a.removeAttribute('aria-current');
     762    }catch(e){}
     763  });
     764}
     765
     766function itdnaUnsavedMain(){
     767  var form=document.querySelector('.itdna-main .itdna-settings-form[data-itdna-dirty="1"]');
     768  return !!form;
     769}
     770
     771function itdnaBindDirtyTracking(){
     772  var main=document.querySelector('.itdna-main');if(!main)return;
     773  main.querySelectorAll('.itdna-settings-form').forEach(function(form){
     774    if(form.getAttribute('data-itdna-dirty-bound')==='1')return;
     775    form.setAttribute('data-itdna-dirty-bound','1');
     776    form.addEventListener('change',function(){form.setAttribute('data-itdna-dirty','1');});
     777    form.addEventListener('input',function(){form.setAttribute('data-itdna-dirty','1');});
     778    form.addEventListener('submit',function(){form.removeAttribute('data-itdna-dirty');});
     779  });
     780}
     781
     782var itdnaNavSeq=0,itdnaNavController=null,itdnaNavTimeout=null;
     783var itdnaNavCache=new Map();
     784function itdnaTabFromUrl(url){
     785  try{var u=new URL(url,location.href);return u.searchParams.get('tab')||'dashboard';}catch(e){return 'dashboard';}
     786}
     787function itdnaNavAjaxUrl(url){
     788  var tab=itdnaTabFromUrl(url);
     789  var ajax=(window.ITDNA_TC_LIVE&&ITDNA_TC_LIVE.ajaxUrl)?ITDNA_TC_LIVE.ajaxUrl:(location.origin+'/wp-admin/admin-ajax.php');
     790  var u=new URL(ajax,location.href);
     791  u.searchParams.set('action','itdna_tc_admin_tab');
     792  u.searchParams.set('tab',tab);
     793  u.searchParams.set('nonce',(window.ITDNA_TC_LIVE&&ITDNA_TC_LIVE.navNonce)||'');
     794  u.searchParams.set('_itdna_nav_ts',String(Date.now()));
     795  return u.toString();
     796}
     797function itdnaApplyMainHtml(html,url,pushState,seq){
     798  if(seq!==itdnaNavSeq)return false;
     799  var doc=new DOMParser().parseFromString(html,'text/html');
     800  var next=doc.querySelector('.itdna-main');
     801  var current=document.querySelector('.itdna-main');
     802  if(!next||!current)throw new Error('Turbo Cache content area not found');
     803  var tab=next.getAttribute('data-itdna-tab')||itdnaTabFromUrl(url);
     804  current.replaceWith(next);
     805  itdnaSetActiveNav(tab);
     806  itdnaBusyClear(120);
     807  if(pushState)history.pushState({itdnaTurboTab:tab},'',url);
     808  itdnaInitAdminMain();
     809  itdnaBindDirtyTracking();
     810  document.dispatchEvent(new CustomEvent('itdna:adminTabReady',{detail:{tab:tab}}));
     811  requestAnimationFrame(function(){
     812    next.classList.add('itdna-nav-entered');
     813    requestAnimationFrame(function(){next.classList.remove('itdna-nav-entered');});
     814  });
     815  return true;
     816}
     817function itdnaNavigate(url,pushState){
     818  var current=document.querySelector('.itdna-main');
     819  if(!current){location.href=url;return;}
     820  var tab=itdnaTabFromUrl(url);
     821  var seq=++itdnaNavSeq;
     822
     823  // Never swallow a second click. A newer click cancels the older in-flight tab request.
     824  if(itdnaNavController){try{itdnaNavController.abort();}catch(e){}}
     825  if(itdnaNavTimeout){clearTimeout(itdnaNavTimeout);itdnaNavTimeout=null;}
     826  itdnaNavController=(typeof AbortController!=='undefined')?new AbortController():null;
     827
     828  itdnaSetActiveNav(tab); // instant visual response to the click
     829  var activeLink=document.querySelector('.itdna-sidebar nav a.active');
     830  var openingLabel=activeLink?String(activeLink.textContent||'').trim():'section';
     831  itdnaBusyNotice('Opening '+openingLabel+'…');
     832  current.classList.add('itdna-nav-loading');
     833  current.setAttribute('aria-busy','true');
     834
     835  var cached=itdnaNavCache.get(tab);
     836  if(cached && (Date.now()-cached.time)<30000){
     837    try{
     838      itdnaApplyMainHtml(cached.html,url,pushState,seq);
     839      itdnaNavController=null;
     840      return;
     841    }catch(e){itdnaNavCache.delete(tab);}
     842  }
     843
     844  var ajaxUrl=itdnaNavAjaxUrl(url);
     845  var fetchOpts={method:'GET',credentials:'same-origin',cache:'no-store',headers:{'X-Requested-With':'XMLHttpRequest'}};
     846  if(itdnaNavController)fetchOpts.signal=itdnaNavController.signal;
     847  itdnaNavTimeout=setTimeout(function(){
     848    if(seq!==itdnaNavSeq)return;
     849    if(itdnaNavController){try{itdnaNavController.abort();}catch(e){}}
     850    location.href=url;
     851  },12000);
     852
     853  fetch(ajaxUrl,fetchOpts)
     854    .then(function(r){if(!r.ok)throw new Error('HTTP '+r.status);return r.text();})
     855    .then(function(html){
     856      if(seq!==itdnaNavSeq)return;
     857      if(itdnaNavTimeout){clearTimeout(itdnaNavTimeout);itdnaNavTimeout=null;}
     858      itdnaNavCache.set(tab,{html:html,time:Date.now()});
     859      // Keep cache small and predictable.
     860      if(itdnaNavCache.size>8){var first=itdnaNavCache.keys().next();if(!first.done)itdnaNavCache.delete(first.value);}
     861      itdnaApplyMainHtml(html,url,pushState,seq);
     862    })
     863    .catch(function(err){
     864      if(seq!==itdnaNavSeq)return;
     865      if(err&&err.name==='AbortError')return;
     866      location.href=url;
     867    })
     868    .finally(function(){
     869      if(seq!==itdnaNavSeq)return;
     870      if(itdnaNavTimeout){clearTimeout(itdnaNavTimeout);itdnaNavTimeout=null;}
     871      itdnaNavController=null;
     872      var m=document.querySelector('.itdna-main');
     873      if(m){m.classList.remove('itdna-nav-loading');m.removeAttribute('aria-busy');}
     874    });
     875}
     876
     877function itdnaBindPartialNavigation(){
     878  if(window.__itdnaPartialNavBound)return;window.__itdnaPartialNavBound=1;
     879  document.addEventListener('click',function(e){
     880    if(e.defaultPrevented||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;
     881
     882    var toolbarPurge=e.target&&e.target.closest?e.target.closest('#wp-admin-bar-itdna-turbo-cache-purge > a'):null;
     883    if(toolbarPurge){
     884      try{var purgeUrl=new URL(toolbarPurge.href,location.href);purgeUrl.searchParams.set('return_to',location.href);toolbarPurge.href=purgeUrl.toString();}catch(err){}
     885      return;
     886    }
     887
     888    var a=e.target&&e.target.closest?e.target.closest('.itdna-sidebar nav a'):null;
     889    if(!a||a.classList.contains('itdna-buy-link')||a.target==='_blank'||a.hasAttribute('download'))return;
     890    var u;
     891    try{u=new URL(a.href,location.href);}catch(err){return;}
     892    if(u.origin!==location.origin||u.searchParams.get('page')!=='itdna-turbo-cache')return;
     893    if(itdnaUnsavedMain()&&!window.confirm('You have unsaved Turbo Cache changes. Open another section without saving?'))return;
     894    e.preventDefault();itdnaNavigate(u.href,true);
     895  });
     896  window.addEventListener('popstate',function(){
     897    var u=new URL(location.href);
     898    if(u.searchParams.get('page')==='itdna-turbo-cache')itdnaNavigate(u.href,false);
     899  });
     900}
     901
     902function itdnaBoot(){itdnaBindGlobalActionFeedback();itdnaBindPartialNavigation();itdnaInitAdminMain();itdnaBindDirtyTracking();}
     903if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',itdnaBoot,{once:true});else itdnaBoot();
    54904})();
  • indiatvdna-turbo-cache-lite/trunk/indiatvdna-turbo-cache.php

    r3744271 r3763637  
    11<?php
    22/**
     3 * Plugin Name: IndiaTVDNA Turbo Cache – Speed & Performance Optimization
    34 * Plugin URI: https://indiatvdna.com/product-category/wordpress-plugins/turbo-cache-pro-wordpress-plugins/
    4  * Plugin Name: IndiaTVDNA Turbo Cache – Speed & Performance Optimization
    5  * Description: Free WordPress performance plugin with page cache, GZIP HTML, HTTP 304 validation, CSS/HTML optimization, Woo safety, preload, diagnostics, safe database cleanup and clear Full-version previews.
    6  * Version: 1.4.8
     5 * Description: Safe-first WordPress performance suite with page cache, preload, CSS/JS/media optimization, object cache, Cloudflare/CDN, diagnostics and safe automation.
     6 * Version: 1.4.9
    77 * Author: IndiaTVDNA
    88 * Author URI: https://indiatvdna.com/
    … …  
    1212 * Text Domain: indiatvdna-turbo-cache-lite
    1313 */
    14 
    1514if (!defined('ABSPATH')) { exit; }
    1615
    17 define('ITDNA_TC_LITE_VERSION', '1.4.8');
    18 define('ITDNA_TC_LITE_FILE', __FILE__);
    19 define('ITDNA_TC_LITE_DIR', plugin_dir_path(__FILE__));
    20 define('ITDNA_TC_LITE_URL', plugin_dir_url(__FILE__));
    21 define('ITDNA_TC_LITE_CACHE_DIR', WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache-lite/');
    22 define('ITDNA_TC_BUY_URL', 'https://indiatvdna.com/product-category/wordpress-plugins/turbo-cache-pro-wordpress-plugins/');
    23 
    24 require_once ITDNA_TC_LITE_DIR . 'includes/class-itdna-lite-cache.php';
    25 require_once ITDNA_TC_LITE_DIR . 'includes/class-itdna-lite-performance.php';
    26 require_once ITDNA_TC_LITE_DIR . 'includes/class-itdna-lite-admin.php';
    27 
    28 register_activation_hook(__FILE__, array('ITDNA_Lite_Cache', 'activate'));
    29 register_deactivation_hook(__FILE__, array('ITDNA_Lite_Cache', 'deactivate'));
    30 
    31 
    32 add_action('plugins_loaded', static function () {
    33     ITDNA_Lite_Cache::instance();
    34     ITDNA_Lite_Performance::instance();
    35     if (is_admin()) {
    36         ITDNA_Lite_Admin::instance();
    37     }
    38 }, 1);
     16// The public plugin ships full Free functionality, not disabled paid algorithms.
     17// Premium implementations are distributed in the separate external Pro plugin.
     18if (!defined('ITDNA_TC_FREE_EDITION')) { define('ITDNA_TC_FREE_EDITION', true); }
     19if (!defined('ITDNA_TC_PRO_URL')) {
     20    define('ITDNA_TC_PRO_URL', 'https://indiatvdna.com/product-category/wordpress-plugins/turbo-cache-pro-wordpress-plugins/');
     21}
     22function itdna_tc_free_safe_options($value) {
     23    if (!is_array($value)) { return $value; }
     24    foreach (array('rum_auto_tune') as $flag) {
     25        $value[$flag] = 0;
     26    }
     27    return $value;
     28}
     29// Legacy options from a former private Pro install cannot activate omitted code.
     30add_filter('option_itdna_tc_options', 'itdna_tc_free_safe_options', 99);
     31// On saving FREE options, keep only the separately distributed auto-tune engine disabled.
     32add_filter('pre_update_option_itdna_tc_options', 'itdna_tc_free_safe_options', 99);
     33
     34// Tiny read-only origin challenge for Auto Best. The early cache must make its
     35// normal cookie decision first; this header does NOT force an early-cache bypass.
     36// Works even when the optimized frontend skips the full plugin runtime.
     37if (!empty($_SERVER['HTTP_X_ITDNA_AUTO_COOKIE_PROBE'])) {
     38    require_once __DIR__ . '/includes/class-itdna-auto-cookie-probe.php';
     39    add_action('send_headers', array('ITDNA_Auto_Cookie_Probe', 'stamp_origin'), 1);
     40}
     41
     42// Master Pause is checked BEFORE private-cookie and frontend hooks. When OFF,
     43// visitors, REST, cron, WP-CLI and third-party admin screens do not boot Turbo.
     44// Administrators retain a tiny independent Dashboard to turn the engine ON.
     45if ((string)get_option('itdna_tc_master_enabled', '1') === '0') {
     46    if (is_admin() && !(defined('DOING_CRON') && DOING_CRON)) {
     47        if (!defined('ITDNA_TC_VERSION')) { define('ITDNA_TC_VERSION', '1.4.9'); }
     48        if (!defined('ITDNA_TC_FILE')) { define('ITDNA_TC_FILE', __FILE__); }
     49        require_once __DIR__.'/includes/class-itdna-master-control.php';
     50        ITDNA_Master_Control::boot_paused();
     51    }
     52    return;
     53}
     54if (is_admin() && !(defined('DOING_CRON') && DOING_CRON)) {
     55    // Native form submission; does not depend on admin AJAX or monitor polling.
     56    require_once __DIR__.'/includes/class-itdna-master-control.php';
     57    ITDNA_Master_Control::boot();
     58}
     59
     60// advanced-cache.php can classify a logged-in/private *frontend* request before
     61// WordPress loads normal plugins. Never let that sentinel short-circuit wp-admin,
     62// REST, cron or WP-CLI: those control-plane requests still need the lightweight
     63// router so the Turbo menu/actions/endpoints remain available.
     64$itdna_tc_early_uri = isset($_SERVER['REQUEST_URI']) && is_scalar($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash(is_scalar($_SERVER['REQUEST_URI'] ?? null) ? (string)$_SERVER['REQUEST_URI'] : '')) : '';
     65$itdna_tc_early_control_plane =
     66    (defined('WP_ADMIN') && WP_ADMIN) ||
     67    (defined('DOING_CRON') && DOING_CRON) ||
     68    (defined('WP_CLI') && WP_CLI) ||
     69    ($itdna_tc_early_uri !== '' && (
     70        strpos($itdna_tc_early_uri, '/wp-admin/') !== false ||
     71        strpos($itdna_tc_early_uri, '/wp-json/') !== false ||
     72        strpos($itdna_tc_early_uri, 'rest_route=') !== false ||
     73        strpos($itdna_tc_early_uri, '/wp-cron.php') !== false
     74    ));
     75if (defined('ITDNA_TC_PRIVATE_ZERO_LOAD') && ITDNA_TC_PRIVATE_ZERO_LOAD && !$itdna_tc_early_control_plane) {
     76    if (!headers_sent()) {
     77        header('Cache-Control: private, no-store, no-cache, must-revalidate, max-age=0', true);
     78        header('X-LiteSpeed-Cache-Control: no-cache', true);
     79        header('CDN-Cache-Control: no-store, max-age=0', true);
     80        header('Cloudflare-CDN-Cache-Control: no-store, max-age=0', true);
     81        header('X-ITDNA-Runtime: private-cross-layer-zero-load', true);
     82    }
     83    // The logged-in private fast-path bypasses the normal plugin runtime.
     84    // Attach ONLY the tiny per-page asset manager when user-scoped rules exist.
     85    // No cache/optimizer or telemetry is enabled for private sessions.
     86    if (function_exists('get_option') && get_option('itdna_tc_lab_asset_rules',array())) {
     87        require_once __DIR__.'/includes/class-itdna-pro-lab.php';
     88        ITDNA_Pro_Lab::register_frontend_only();
     89    }
     90    unset($itdna_tc_early_uri, $itdna_tc_early_control_plane);
     91    return;
     92}
     93unset($itdna_tc_early_uri, $itdna_tc_early_control_plane);
     94
     95/*
     96 * v1.4.29 password-protected reader session fail-closed fallback when
     97 * advanced-cache.php is absent/disabled. Never affect wp-admin or REST.
     98 */
     99if (!(defined('WP_ADMIN') && WP_ADMIN) && !(defined('DOING_CRON') && DOING_CRON) && !(defined('WP_CLI') && WP_CLI)) {
     100    $itdna_pass_uri = esc_url_raw(wp_unslash(is_scalar($_SERVER['REQUEST_URI'] ?? null) ? (string)$_SERVER['REQUEST_URI'] : ''));
     101    $itdna_pass_control = preg_match('~(?:/wp-admin(?:/|$)|/wp-login\.php(?:\?|$)|/wp-json(?:/|$)|/wp-cron\.php(?:\?|$)|[?&]rest_route=)~i', $itdna_pass_uri);
     102    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Reviewed compatibility exception: Keep type-checked transport bytes exact for cache/private-session decisions; consumers perform protocol-specific checks. Text sanitization would alter encoded cache keys or authentication data.
     103    $itdna_pass_cookie = (string)($_SERVER['HTTP_COOKIE'] ?? $_SERVER['REDIRECT_HTTP_COOKIE'] ?? '');
     104    if (!$itdna_pass_control && preg_match('/(?:^|;\s*)wp-postpass_[^=;]*\s*=/i', $itdna_pass_cookie)) {
     105        if (!defined('DONOTCACHEPAGE')) { define('DONOTCACHEPAGE', true); }
     106        if (!headers_sent()) {
     107            header('Cache-Control: private, no-store, no-cache, must-revalidate, max-age=0', true);
     108            header('X-LiteSpeed-Cache-Control: no-cache', true);
     109            header('CDN-Cache-Control: no-store, max-age=0', true);
     110            header('Cloudflare-CDN-Cache-Control: no-store, max-age=0', true);
     111            header('Surrogate-Control: no-store', true);
     112            header('Vary: Cookie', false);
     113            header('X-ITDNA-Runtime: password-cookie-private-bypass', true);
     114        }
     115        unset($itdna_pass_uri, $itdna_pass_control, $itdna_pass_cookie);
     116        return;
     117    }
     118    unset($itdna_pass_uri, $itdna_pass_control, $itdna_pass_cookie);
     119}
     120
     121/*
     122 * Private frontend absolute bypass.
     123 * Detect the authenticated WordPress cookie without bootstrapping the user API.
     124 * advanced-cache.php already emitted no-store headers before WordPress loaded, so
     125 * the normal plugin does no hooks, no toolbar node, no option reads and no classes.
     126 */
     127if (!(defined('WP_ADMIN') && WP_ADMIN) && !(defined('DOING_CRON') && DOING_CRON) && !(defined('WP_CLI') && WP_CLI)) {
     128    $itdna_tc_uri = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash(is_scalar($_SERVER['REQUEST_URI'] ?? null) ? (string)$_SERVER['REQUEST_URI'] : '')) : '';
     129    $itdna_tc_is_rest = $itdna_tc_uri !== '' && (strpos($itdna_tc_uri, '/wp-json/') !== false || strpos($itdna_tc_uri, 'rest_route=') !== false);
     130    if (!$itdna_tc_is_rest) {
     131        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Reviewed compatibility exception: Keep type-checked transport bytes exact for cache/private-session decisions; consumers perform protocol-specific checks. Text sanitization would alter encoded cache keys or authentication data.
     132        $itdna_tc_cookie_header = isset($_SERVER['HTTP_COOKIE']) ? (string) $_SERVER['HTTP_COOKIE'] : '';
     133        if ($itdna_tc_cookie_header !== '' && stripos($itdna_tc_cookie_header, 'wordpress_logged_in_') !== false) {
     134            // Fallback headers in case WP_CACHE/advanced-cache.php is disabled.
     135            if (!headers_sent()) {
     136                header('Cache-Control: private, no-store, no-cache, must-revalidate, max-age=0', true);
     137                header('X-LiteSpeed-Cache-Control: no-cache', true);
     138                header('CDN-Cache-Control: no-store, max-age=0', true);
     139                header('Cloudflare-CDN-Cache-Control: no-store, max-age=0', true);
     140                header('X-ITDNA-Runtime: private-absolute-bypass', true);
     141            }
     142    // The logged-in private fast-path bypasses the normal plugin runtime.
     143    // Attach ONLY the tiny per-page asset manager when user-scoped rules exist.
     144    // No cache/optimizer or telemetry is enabled for private sessions.
     145    if (function_exists('get_option') && get_option('itdna_tc_lab_asset_rules',array())) {
     146        require_once __DIR__.'/includes/class-itdna-pro-lab.php';
     147        ITDNA_Pro_Lab::register_frontend_only();
     148    }
     149            unset($itdna_tc_uri, $itdna_tc_is_rest, $itdna_tc_cookie_header);
     150            return;
     151        }
     152        unset($itdna_tc_cookie_header);
     153    }
     154    unset($itdna_tc_uri, $itdna_tc_is_rest);
     155}
     156
     157define('ITDNA_TC_VERSION','1.4.9');
     158define('ITDNA_TC_FILE',__FILE__);
     159define('ITDNA_TC_DIR',plugin_dir_path(__FILE__));
     160// Preserve settings when upgrading the existing WordPress.org Lite plugin.
     161require_once ITDNA_TC_DIR . 'includes/class-itdna-lite-upgrade.php';
     162itdna_tc_migrate_lite_148_settings();
     163// Opt-in FREE Workers Static Assets: independent secondary copy.
     164try {
     165    require_once ITDNA_TC_DIR . 'includes/class-itdna-workers-assets.php';
     166} catch (\Throwable $e) {
     167    // Optional Workers error must not bring down WordPress core or Turbo's cache.
     168    $GLOBALS['itdna_tc_workers_boot_failed']=true;
     169    // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Reviewed compatibility exception: Production failure diagnostics are intentional and do not render to visitors. Removing this logging would remove failure visibility.
     170    if (function_exists('error_log')) error_log('IndiaTVDNA Turbo Cache: Workers optional module unavailable '.get_class($e).' at '.basename($e->getFile()).':'.$e->getLine());
     171}
     172/*
     173 * Stable production boot. The early drop-ins load BEFORE ordinary plugins, so
     174 * activation and upgrade must retire ONLY our old drop-ins before the next
     175 * request. The standard WordPress-side engine boots normally; the independent
     176 * early-cache acceleration is enabled only after explicit verified repair.
     177 */
     178function itdna_tc_recovery_disable_delivery() {
     179    $dir = WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache/';
     180    if (!is_dir($dir) && function_exists('wp_mkdir_p')) { wp_mkdir_p($dir); }
     181    if (is_dir($dir)) {
     182        // phpcs:ignore PluginCheck.CodeAnalysis.WriteFile.PluginDirectoryWrite -- Reviewed compatibility exception: The destination is the explicit wp-content cache/drop-in path, not this plugin directory. Runtime sentinels and owned drop-in rollback must survive plugin upgrades.
     183        @file_put_contents($dir . 'runtime-disabled.flag', "1\n", LOCK_EX);
     184        // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink -- Reviewed compatibility exception: Cache/runtime local filesystem operation: retain native atomic rename, checked deletion result, permissions or timestamps. Replacing it with remote/copy-based WP_Filesystem operations changes the cache consistency contract.
     185        @unlink($dir . 'runtime-active.flag');
     186    }
     187}
     188/**
     189 * Never remove or overwrite third-party drop-ins. Renaming OUR files makes
     190 * WordPress's native cache implementation take over on the next request, even
     191 * when the old early runtime didn't support a recovery sentinel.
     192 */
     193function itdna_tc_retire_old_owned_dropins() {
     194    foreach (array(
     195        'advanced-cache.php' => 'IndiaTVDNA Turbo Cache Early Drop-in',
     196        'object-cache.php' => 'IndiaTVDNA Turbo Cache Object Cache Drop-in',
     197    ) as $name => $marker) {
     198        $path = WP_CONTENT_DIR . '/' . $name;
     199        if (!is_file($path)) { continue; }
     200        $head = @file_get_contents($path, false, null, 0, 1024);
     201        if (!is_string($head) || strpos($head, $marker) === false) { continue; }
     202        $backup = WP_CONTENT_DIR . '/' . $name . '.itdna-retired-148.php';
     203        // Never overwrite a backup; if one already contains exactly this owned
     204        // drop-in, deleting the redundant active copy is safe and idempotent.
     205        // phpcs:ignore PluginCheck.CodeAnalysis.WriteFile.PluginDirectoryWrite,WordPress.WP.AlternativeFunctions.rename_rename -- Reviewed compatibility exception: Cache/runtime local filesystem operation: retain native atomic rename, checked deletion result, permissions or timestamps. Replacing it with remote/copy-based WP_Filesystem operations changes the cache consistency contract. The destination is the explicit wp-content cache/drop-in path, not this plugin directory. Runtime sentinels and owned drop-in rollback must survive plugin upgrades.
     206        if (!file_exists($backup)) { @rename($path, $backup); }
     207        elseif (is_file($backup) && is_file($path)) {
     208            $old_hash = @hash_file('sha256', $backup);
     209            $live_hash = @hash_file('sha256', $path);
     210            if (is_string($old_hash) && $old_hash !== '' && hash_equals($old_hash, (string)$live_hash)) {
     211                // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink -- Reviewed compatibility exception: Cache/runtime local filesystem operation: retain native atomic rename, checked deletion result, permissions or timestamps. Replacing it with remote/copy-based WP_Filesystem operations changes the cache consistency contract.
     212                @unlink($path);
     213            }
     214        }
     215    }
     216}
     217/** A verified working owned cache must NEVER be disabled just because its ZIP changed. */
     218function itdna_tc_owned_delivery_operational() {
     219    if (get_option('itdna_tc_recovery_mode', 0)) { return false; }
     220    if (!defined('WP_CACHE') || !WP_CACHE) { return false; }
     221    $dropin = WP_CONTENT_DIR . '/advanced-cache.php';
     222    $dir = WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache/';
     223    $head = is_file($dropin) ? @file_get_contents($dropin, false, null, 0, 1024) : false;
     224    return is_string($head) && strpos($head, 'IndiaTVDNA Turbo Cache Early Drop-in') !== false
     225        && is_file($dir.'early-config.php') && is_file($dir.'runtime-active.flag')
     226        && !is_file($dir.'runtime-disabled.flag');
     227}
     228function itdna_tc_stable_activate($network_wide = false) {
     229    $was_live = itdna_tc_owned_delivery_operational();
     230    update_option('itdna_tc_recovery_mode', 0, false);
     231    update_option('itdna_tc_delivery_auto_repair_disabled', 1, false);
     232    update_option('itdna_tc_stable_guard_version', ITDNA_TC_VERSION, false);
     233    // A brand-new install has no page-cache drop-in. A previously healthy
     234    // installation keeps its working drop-in, configuration and active flag.
     235    // Do not retire our object-cache.php either: it is an independent service.
     236    if (!$was_live) {
     237        itdna_tc_recovery_disable_delivery();
     238        update_option('itdna_tc_delivery_setup_pending', 1, false);
     239    } else {
     240        delete_option('itdna_tc_delivery_setup_pending');
     241    }
     242    wp_clear_scheduled_hook('itdna_tc_cache_delivery_repair_event');
     243    wp_clear_scheduled_hook('itdna_tc_first_install_bootstrap_event');
     244}
     245function itdna_tc_stable_deactivate() {
     246    wp_clear_scheduled_hook('itdna_tc_host_guard_watch');
     247    itdna_tc_recovery_disable_delivery();
     248    // The removed plugin must not leave its pre-bootstrap code running.
     249    itdna_tc_retire_old_owned_dropins();
     250}
     251register_activation_hook(ITDNA_TC_FILE,'itdna_tc_stable_activate');
     252register_deactivation_hook(ITDNA_TC_FILE,'itdna_tc_stable_deactivate');
     253
     254// ZIP updates are NOT activation events. The former upgrade hook retired a
     255// working advanced-cache.php on EVERY VERSION CHANGE, producing the recurring
     256// "cache delivery is not active" notice. Preserve healthy infrastructure.
     257if ((string)get_option('itdna_tc_stable_guard_version','') !== ITDNA_TC_VERSION) {
     258    $was_live = itdna_tc_owned_delivery_operational();
     259    update_option('itdna_tc_stable_guard_version', ITDNA_TC_VERSION, false);
     260    update_option('itdna_tc_delivery_auto_repair_disabled', 1, false);
     261    if (!$was_live && !get_option('itdna_tc_recovery_mode', 0)) {
     262        // Legacy v1.3.54 installations were left with a disabled cache on each
     263        // upgrade. Allow a ONE-TIME, admin-only guarded setup below.
     264        update_option('itdna_tc_delivery_setup_pending', 1, false);
     265    }
     266    // Never silently clear a genuine fatal-recovery state or delete third-party
     267    // drop-ins. The owner can use the Recovery dashboard when necessary.
     268}
     269if (get_option('itdna_tc_recovery_mode', 0)) {
     270    require_once ITDNA_TC_DIR.'includes/bootstrap-recovery.php';
     271    return;
     272}
     273
     274// Show proof that the known legacy fatal was cleared. Never claim an active
     275// page-cache drop-in or suppress a new recovery state just to display success.
     276add_action('admin_notices', static function() {
     277    if (!current_user_can('manage_options') || get_option('itdna_tc_recovery_mode', 0)) { return; }
     278    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reviewed compatibility exception: Read-only route/tab/notice/cache-eligibility selection; this request field is not authority to mutate settings. Action handlers retain their own authentication.
     279    if (!isset($_GET['itdna_recovery_fixed']) || (string)$_GET['itdna_recovery_fixed'] !== '1') { return; }
     280    $record = get_option('itdna_tc_last_fixed_legacy_error', array());
     281    if (!is_array($record) || ($record['fixed_in'] ?? '') !== ITDNA_TC_VERSION) { return; }
     282    echo '<div class="notice notice-success is-dismissible"><p><strong>IndiaTVDNA Turbo Cache:</strong> The previously recorded WP_Hook scheduler fatal was verified and recovery has been cleared once. The current engine is active; please test your site and watch for new errors. Cache delivery remains subject to separate verification.</p></div>';
     283});
     284
     285// v1.3.51: configurable advisory-lock slots (default max 1), with a
     286// configurable post-event quiet period (default 2 seconds).
     287require_once ITDNA_TC_DIR.'includes/class-itdna-strict-event-scheduler.php';
     288require_once ITDNA_TC_DIR.'includes/class-itdna-server-telemetry.php';
     289require_once ITDNA_TC_DIR.'includes/class-itdna-hosting-guard.php';
     290require_once ITDNA_TC_DIR.'includes/class-itdna-real-image-pool.php';
     291/**
     292 * Complete an explicitly requested repair on the FIRST request that actually
     293 * loads WP_CACHE=true. No wp-config/.htaccess edits and no automatic enabling
     294 * after failed prerequisites; this is a verification-only transition.
     295 */
     296function itdna_tc_finish_verified_delivery() {
     297    if (!get_option('itdna_tc_delivery_activation_pending', 0) || get_option('itdna_tc_recovery_mode', 0)) { return; }
     298    if ((string)get_option('itdna_tc_master_enabled', '1') === '0' || is_file(WP_CONTENT_DIR.'/cache/indiatvdna-turbo-cache/master-paused.flag')) { return; }
     299    if (!defined('WP_CACHE') || !WP_CACHE) { return; }
     300    $dropin = WP_CONTENT_DIR . '/advanced-cache.php';
     301    $cfg = WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache/early-config.php';
     302    $runtime = ITDNA_TC_DIR . 'dropins/advanced-cache-runtime.php';
     303    $head = is_file($dropin) ? @file_get_contents($dropin, false, null, 0, 1024) : false;
     304    if (!is_string($head) || strpos($head, 'IndiaTVDNA Turbo Cache Early Drop-in') === false || !is_file($cfg) || !is_file($runtime)) { return; }
     305    foreach (array($dropin, $runtime, $cfg) as $file) {
     306        $content = @file_get_contents($file);
     307        if (!is_string($content) || $content === '' || strlen($content) > 1048576) { return; }
     308        try { token_get_all($content, TOKEN_PARSE); }
     309        catch (\ParseError $error) { return; }
     310    }
     311    $config = @include $cfg;
     312    if (!is_array($config) || empty($config['enabled'])) { return; }
     313    $cache_dir = WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache/';
     314    // phpcs:ignore PluginCheck.CodeAnalysis.WriteFile.PluginDirectoryWrite -- Reviewed compatibility exception: The destination is the explicit wp-content cache/drop-in path, not this plugin directory. Runtime sentinels and owned drop-in rollback must survive plugin upgrades.
     315    if (@file_put_contents($cache_dir.'runtime-active.flag', "1\n", LOCK_EX) === false) { return; }
     316    // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink -- Reviewed compatibility exception: Cache/runtime local filesystem operation: retain native atomic rename, checked deletion result, permissions or timestamps. Replacing it with remote/copy-based WP_Filesystem operations changes the cache consistency contract.
     317    if (is_file($cache_dir.'runtime-disabled.flag') && !@unlink($cache_dir.'runtime-disabled.flag')) {
     318        // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink -- Reviewed compatibility exception: Cache/runtime local filesystem operation: retain native atomic rename, checked deletion result, permissions or timestamps. Replacing it with remote/copy-based WP_Filesystem operations changes the cache consistency contract.
     319        @unlink($cache_dir.'runtime-active.flag');
     320        return;
     321    }
     322    delete_option('itdna_tc_delivery_activation_pending');
     323}
     324add_action('admin_init','itdna_tc_finish_verified_delivery', 3);
     325
     326// Trap fatals that point into this plugin. The next WordPress request runs the
     327// minimal recovery dashboard, rather than repeatedly loading the crash path.
     328register_shutdown_function(static function() {
     329    $err = error_get_last();
     330    if (!is_array($err) || !in_array((int)($err['type'] ?? 0), array(E_ERROR,E_PARSE,E_CORE_ERROR,E_COMPILE_ERROR,E_USER_ERROR,E_RECOVERABLE_ERROR), true)) { return; }
     331    $path = str_replace('\\','/',(string)($err['file'] ?? ''));
     332    $plugin = str_replace('\\','/',ITDNA_TC_DIR);
     333    if (strpos($path, $plugin) !== 0) { return; }
     334    if (!function_exists('update_option')) { return; }
     335    update_option('itdna_tc_last_plugin_fatal', array(
     336        'time'=>time(), 'version'=>ITDNA_TC_VERSION, 'file'=>substr($path,strlen($plugin)),
     337        'line'=>(int)($err['line'] ?? 0),
     338        'message'=>substr((string)($err['message'] ?? ''),0,800),
     339    ), false);
     340    update_option('itdna_tc_recovery_mode', 1, false);
     341    itdna_tc_recovery_disable_delivery();
     342});
     343require_once ITDNA_TC_DIR.'includes/bootstrap-router.php';
  • indiatvdna-turbo-cache-lite/trunk/readme.txt

    r3744271 r3763637  
    11=== IndiaTVDNA Turbo Cache – Speed & Performance Optimization ===
    22Contributors: msntargetcom, indiatvdna
    3 Tags: cache, performance, minify, cloudflare, cdn
     3Tags: cache, performance, cloudflare, cdn, optimization
    44Requires at least: 6.9
    55Requires PHP: 7.4
    66Tested up to: 7.1
    7 Stable tag: 1.4.8
     7Stable tag: 1.4.9
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    1010
    11 Free WordPress caching, CSS/HTML optimization, preload, Cloudflare purge, CDN delivery and diagnostics.
     11Cache and optimization controls for WordPress, with performance monitoring and optional CDN integrations.
    1212
    1313== Description ==
     14IndiaTVDNA Turbo Cache provides page caching, cache preload, CSS/JS/image optimization, object caching, diagnostics, Cloudflare/CDN tools and WooCommerce safety controls. Free features are fully available without purchasing a subscription or installing a Pro package.
    1415
    15 IndiaTVDNA Turbo Cache - Speed & Performance Optimization is a free WordPress performance plugin with functional caching, safe optimization and diagnostic tools. It is not a trial. The separate *Turbo Cache Pro* package offers additional performance and CDN features; those engines are not bundled in this WordPress.org download.
     16Free includes local real-user performance reporting, anonymous predictive page warming, and per-page optimization profiles (all opt-in where appropriate), but not RUM Safe Auto Tune. Free additionally includes functioning Predictive Cache Engine and Per-Page Optimization Profiles. An optional independently distributed Pro edition has seven separate enhancement groups: verified fastest CDN route selection, Cloudflare R2 Smart Mirror, Real User Performance Auto Tune, advanced Unused CSS review/approval, Workers queue watchdog, responsive image delivery policy and guarded WooCommerce product warming. Their source code is not included in this WordPress.org-candidate ZIP. The preview fields shown in Free are descriptions of separately distributed optional features; there is no bundled paid unlocker. In Free, Workers post selection defaults to 100 latest plus 50 extra popular posts but both can be increased or decreased without payment. Background sync continues in safe small batches; hosting resources and Cloudflare service-side limits can affect completion time. Pro adds independent schedule recovery and monitoring, not higher numeric quotas.
    1617
    17 = Included in this free plugin =
     18Third-party services are optional and require separately supplied credentials/consent. The local plugin can work without third-party service accounts. When enabling Cloudflare or other external services, review that provider's terms and data/privacy policies. Local browser measurement reporting posts sampled anonymous performance data to this site's own WordPress admin-ajax endpoint, only when learning is enabled; see Privacy & Compatibility for controls. Remote requests to a configured CDN are initiated by settings that you choose to enable.
    1819
    19 * **Page caching:** Anonymous HTML page cache, session-aware bypasses, automatic invalidation and manual purge.
    20 * **HTTP and browser caching:** Optional GZIP copies, ETag / Last-Modified HTTP 304 validation and cache counts / storage statistics.
    21 * **Safe asset optimization:** Conservative HTML cleanup, generated CSS minification copies and local font-display: swap; original stylesheets are not edited.
    22 * **Media loading:** WordPress-core image and iframe lazy-loading support.
    23 * **Preload and maintenance:** Basic Auto Optimize, manual preload, bounded changed-URL warming, expired-transient cleanup and bounded recent-revision cleanup.
    24 * **Cloudflare controls:** Optional credential verification, zone detection, manual purge and administrator-enabled content-change purge.
    25 * **Bring-your-own CDN:** Optional URL rewriting for eligible wp-content / wp-includes assets to an administrator-provided CDN hostname.
    26 * **Diagnostics:** Basic Performance Doctor, cache self-test, local theme/plugin compatibility intelligence, low-overhead cache analytics and generated-asset statistics.
    27 * **WooCommerce safety:** Conservative cache exclusions for logged-in users, cart, checkout, account and session-dependent requests.
    28 * **Portable settings:** JSON export/import without saved Cloudflare secrets, account email or detected zone identifiers.
     20Pro details: https://indiatvdna.com/product-category/wordpress-plugins/turbo-cache-pro-wordpress-plugins/
    2921
    30 Lite features remain usable without a purchase. Any Pro cards displayed in the free administration area are informational previews linking to a separately distributed package, not time-limited premium functionality.
    31 
    32 = Separate Turbo Cache Pro package =
    33 
    34 The following features describe the **separately distributed premium product**. They are **not included in the WordPress.org Lite ZIP**.
    35 
    36 **Smart CDN and Cloudflare Workers**
    37 
    38 * **Cloudflare Workers asset delivery:** Discover, validate, stage and synchronize eligible CSS, JavaScript and image assets through configured, administrator-owned Worker delivery routes.
    39 * **Independent CDN Verification Lab:** Test hosting/origin URLs and Worker URLs independently, with resource-level HTTP responses, latency samples and available HIT / MISS / EXPIRED headers.
    40 * **Origin, hosting CDN and Worker choices:** Guarded Auto-Fastest selection and safe origin fallback for supported assets when a preferred route is not verified or available.
    41 * **Worker deployment controls:** Bounded background jobs, manual discovery/safe-sync action, deployment status and per-file staging diagnostics.
    42 * **Hosting migration visibility:** Distinguish a pending/mismatched origin TLS certificate from an actual Worker failure, without disabling SSL verification.
    43 * **Managed Cloudflare edge features:** Advanced full-page edge-cache rule controls and self-heal for previously plugin-owned rules; first-time installation requires explicit administrator action.
    44 
    45 **Advanced cache and site optimization**
    46 
    47 * Early `advanced-cache.php` delivery, stale-cache safeguards and stampede protection.
    48 * Background AVIF/WebP image conversion with CPU-aware pacing, source fingerprints and duplicate-work prevention.
    49 * Redis/Memcached discovery, object-cache diagnostics and guarded recovery following successful health checks.
    50 * Adaptive preload, advanced asset exclusions, governed CSS rebuilds, cache freshness and targeted invalidation.
    51 * Runtime canary/regression protections, safe rollback, deeper WooCommerce isolation checks and cache-coherence diagnostics.
    52 * Bounded local real-user performance trends and font/CLS diagnostics without a second external analytics beacon.
    53 * Coordinated background scheduling and safeguards to avoid stacking heavy jobs on busy or shared hosting.
    54 
    55 **What Auto-Fastest does not promise:** A reachable or cached Worker URL alone does not establish that every visitor is using it. Route verification, configuration and real visitor delivery must be assessed separately. It is not a guarantee of per-visitor fastest routing, automatic whole-site traffic balancing or server failover.
    56 
    57 **Performance expectations:** The benefit varies with PHP/CPU resources, cache-hit rate, workload, media, hosting/CDN provider, visitor location and network conditions. A low-cost host cannot be guaranteed to match a higher-capacity server for uncached or dynamic requests. No Lighthouse score, percentage gain or universal CDN advantage is guaranteed.
    58 
    59 [Explore IndiaTVDNA Turbo Cache Pro features and licensing](https://indiatvdna.com/product-category/wordpress-plugins/turbo-cache-pro-wordpress-plugins/)
    60 
    61 == External services ==
    62 
    63 IndiaTVDNA Turbo Cache – Speed & Performance Optimization does not automatically send site or visitor data to IndiaTVDNA.
     22== External Services and Privacy ==
     23The core Free cache and optimization features do not require an IndiaTVDNA account.
    6424
    6525= Cloudflare =
    66 Cloudflare integration is optional and OFF by default. It is used only when an administrator explicitly configures/uses the Cloudflare controls. The plugin may send authenticated requests to Cloudflare's API to verify the configured Cloudflare credential, find the zone for the current site and purge Cloudflare cache. These requests include the credential and site/zone information needed for the requested operation. When the administrator chooses legacy Global API Key authentication, the matching Cloudflare account email is also sent because Cloudflare requires it for that legacy authentication method.
     26Optional Cloudflare connection and purge tools communicate with Cloudflare APIs only after the site administrator enables/configures the integration. The request includes the configured API credentials, zone data and site details needed for the chosen operation. Legacy Global API Key authentication also sends the configured account email. See https://www.cloudflare.com/ , https://www.cloudflare.com/privacypolicy/ and https://www.cloudflare.com/terms/ .
    6727
    68 Service: https://www.cloudflare.com/
    69 Privacy Policy: https://www.cloudflare.com/privacypolicy/
    70 Terms: https://www.cloudflare.com/terms/
     28= Cloudflare Workers asset mirror =
     29Only after the administrator configures a Cloudflare account and explicitly selects the Worker setup/sync action, this plugin communicates with that account's Cloudflare Workers API. The setup may upload a static JavaScript Worker module and public CSS, JS, fonts, image files and published public-page cache assets to the account. It does not upload PHP executables, install WordPress plugins from Cloudflare, or send private/checkout/user sessions into a shared CDN cache. Cloudflare hosts the selected public static files and serves eligible requests under its own terms and resource limits. The administrator controls credentials, synchronization and optional cleanup. Free Workers upload jobs remain in small resource-protected batches even when more published posts are selected.
     30Cloudflare privacy: https://www.cloudflare.com/privacypolicy/
     31Cloudflare terms: https://www.cloudflare.com/terms/
    7132
    72 = User-configured CDN =
    73 CDN URL Delivery is optional and OFF by default. The plugin does not choose or create a CDN provider. If an administrator enters a CDN hostname and enables delivery, eligible static asset URLs are rewritten to that hostname. Visitors' browsers may then send normal web requests (such as IP address, user agent and requested asset URL) to the administrator-selected CDN provider. Review the privacy policy and terms of the CDN provider you choose.
     33= Administrator-chosen CDN =
     34When CDN delivery is explicitly enabled, eligible visitors' asset requests are directed to the CDN hostname configured by the administrator. The chosen CDN receives normal HTTP request metadata, such as IP addresses, user agents and requested URLs, subject to its policies.
    7435
    75 = IndiaTVDNA website links =
    76 The admin interface contains optional Full-version purchase links to https://indiatvdna.com/product-category/wordpress-plugins/turbo-cache-pro-wordpress-plugins/. Data is sent to that website only when an administrator chooses to follow a link, according to the website's own terms and privacy policy.
     36= Local performance measurements =
     37Optional browser measurements use a sampled first-party endpoint at this site's own WordPress installation. No IndiaTVDNA-hosted analytics endpoint is required for the Free cache; site administrators should disclose locally collected data in their site's privacy notice as applicable.
    7738
    78 The plugin also adds suggested text to WordPress's Privacy Policy Guide for the optional Cloudflare/CDN features.
     39= IndiaTVDNA purchase link =
     40The Pro purchase links open https://indiatvdna.com/product-category/wordpress-plugins/turbo-cache-pro-wordpress-plugins/ only when an administrator chooses to follow them.
     41
     42== 1.4.9 Changes ==
     43- REV5: Fixed nine output escaping findings in Pro-preview links and Workers numeric fields, and matched the readme plugin title with the main plugin header; no features or settings were changed.
     44- REV4: Removed the paid 100/50 Workers selection quotas in the Free UI, save handlers, and eligible-post discovery. Defaults remain 100 and 50, and background upload/mirror safety limits remain intact.
     45- Normal Workers static asset synchronization and manual CDN setup remain Free; advanced multi-CDN route auto-selection stays in the separately distributed Pro edition.
     46- Cloudflare credentials and remote asset transfers remain opt-in. No remotely downloaded plugin executable code or automatic private-plugin updates are installed by the Free edition.
     47- Seven Pro enhancement groups, including four new advanced workflows, remain in a separately distributed private plugin. Free CSS, Workers, image, and WooCommerce controls remain functional without any purchase.
     48- Predictive Cache Engine and Per-Page Optimization Profiles are fully functional in Free.
     49- Free Workers synchronization defaults to 100 latest plus 50 additional popular posts (with a verified numeric views key); both selection counts are adjustable without a paid limit.
     50- Extended Workers content selection is offered by the separately distributed Pro product.
    7951
    8052== Installation ==
    81 
    82 1. Upload the plugin ZIP in Plugins > Add New > Upload Plugin.
    83 2. Activate IndiaTVDNA Turbo Cache – Speed & Performance Optimization.
    84 3. Open Turbo Cache in wp-admin.
    85 4. Start with Auto Optimize or configure individual Free modules.
    86 5. Test CSS/font optimizations on the front end after enabling them.
    87 6. Configure Cloudflare/CDN only if you already use those external services.
     531. Back up the site. Deactivate and remove the private Pro edition before installing Free. Do not run both simultaneously.
     542. Upload the Free ZIP through Plugins > Add New > Upload Plugin.
     553. Activate the plugin and open Turbo Cache > Dashboard. Configure only the services you want, and verify WooCommerce logged-in/cart bypass on a staging site before production deployment.
    8856
    8957== Frequently Asked Questions ==
     58= Can I run the free version without buying Pro? =
     59Yes. All functionality inside this Free package is available without payment.
    9060
    91 = Is this free plugin a limited trial? =
    92 No. Its listed free functionality has no purchase deadline.
     61= Are the seven separately offered Pro enhancements included in Free? =
     62No. They are upgrade previews for separately distributed software. Free operation does not depend on their code.
    9363
    94 = Are premium engines locked inside the Lite download? =
    95 No. Premium modules are distributed separately; previews in Lite are informational only.
    96 
    97 = Does the free Smart Intelligence feature use an AI service? =
    98 No. The Lite scan is deterministic and runs locally.
    99 
    100 = Does the free plugin turn on Cloudflare by itself? =
    101 No. Cloudflare features are optional and require administrator configuration or action.
    102 
    103 = Does free CDN URL Delivery select or create a CDN provider? =
    104 No. Administrators configure their own CDN hostname, provider and terms.
    105 
    106 = Is Cloudflare Workers CDN included in the free plugin? =
    107 No. Worker synchronization and independent Worker diagnostics are part of the separate Pro package.
    108 
    109 = Does the plugin cache WooCommerce checkout or logged-in pages? =
    110 The free plugin bypasses those requests to avoid caching private or session-specific content.
    111 
    112 = Can Pro guarantee the same speed on every hosting provider? =
    113 No. Cacheable delivery may reduce dependence on origin hosting, but uncached PHP, databases and server capacity still matter.
    114 
    115 == Screenshots ==
    116 
    117 1. Dashboard Overview - Current cache status, quick actions and setup.
    118 2. Page Cache Controls - HTML cache delivery, freshness and storage settings.
    119 3. Performance Doctor - Available basic diagnostics and Pro feature previews.
    120 4. Image Optimizer - Preview of advanced AVIF/WebP controls in the separate Pro edition.
    121 5. Cloudflare Integration - Optional connection, authentication and purge controls.
    122 6. Diagnostics Status - Environment checks and cache health signals.
    123 7. Tools and Diagnostics - Local tests, logs and import/export tools.
    124 8. Image Optimization Controls - Preview of Pro background processing options.
     64= Are remote integrations enabled without my approval? =
     65Cloudflare, Workers and other remote integrations require setup and applicable explicit settings. Review the configuration and privacy details before connecting them.
    12566
    12667== Changelog ==
     68= 1.4.9 =
     69* Update of the previously published Lite plugin, with the same directory, main plugin file, text domain, and contributors.
     70* Retains working Free cache, CDN, optimization, browser diagnostics and admin options; premium algorithms are excluded from the Free release.
     71* Shows contextual information for seven separate Pro enhancement groups, with no paid implementation or unlocker in Free. Existing Free options, including local CSS, image and WooCommerce safety controls, remain functional.
     72* Preserves existing Lite 1.4.8 settings with a non-destructive one-time option migration; an existing newer options record is never overwritten.
     73* Keeps native WordPress.org plugin updates (no private updater or Update URI) and fixes the Free drop-in folder references.
    12774
    12875= 1.4.8 =
    129 * Added a Plugin Homepage link to the main plugin header for WordPress.org.
    130 
     76* Added the plugin homepage link in the WordPress.org main plugin header.
    13177= 1.4.7 =
    132 * Updated the public plugin display name to IndiaTVDNA Turbo Cache - Speed & Performance Optimization.
    133 * Preserved the existing plugin slug, text domain and update path.
    134 
    135 = 1.4.6 =
    136 * Strengthened private/no-store and authenticated-request page-cache bypasses.
    137 * Added HTTP 304 cache validation, WooCommerce safety, analytics and bounded background maintenance.
    138 * Improved cache directory safeguards, optional Cloudflare controls and free/premium separation.
    139 
    140 For older releases (1.4.7–1.0.0), see `changelog.txt`.
     78* Updated the public display name, keeping the plugin slug and text domain.
  • indiatvdna-turbo-cache-lite/trunk/uninstall.php

    r3729757 r3763637  
    22if (!defined('WP_UNINSTALL_PLUGIN')) { exit; }
    33
    4 delete_option('itdna_tc_lite_settings');
    5 delete_option('itdna_tc_lite_last_self_test');
    6 delete_option('itdna_tc_lite_last_cf_purge');
    7 delete_option('itdna_tc_lite_last_purge');
    8 delete_option('itdna_tc_lite_last_changed_warm');
    9 delete_option('itdna_tc_lite_last_preload');
    10 delete_option('itdna_tc_lite_last_db_cleanup');
    11 delete_option('itdna_tc_lite_last_revision_cleanup');
    12 wp_clear_scheduled_hook('itdna_tc_lite_warm_changed_post');
    13 
    14 $itdna_tc_lite_root = WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache-lite/';
     4// Fail closed before any cleanup. If filesystem/DB cleanup later fails, the owned
     5// drop-ins still see the disabled sentinel (or missing owner plugin after deletion)
     6// and cannot keep cache/object-cache behavior active.
     7$itdna_tc_runtime_dir = WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache/';
     8// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_mkdir -- Reviewed compatibility exception: Cache/runtime local filesystem operation: retain native atomic rename, checked deletion result, permissions or timestamps. Replacing it with remote/copy-based WP_Filesystem operations changes the cache consistency contract.
     9if (!is_dir($itdna_tc_runtime_dir)) { @mkdir($itdna_tc_runtime_dir, 0755, true); }
     10// phpcs:ignore PluginCheck.CodeAnalysis.WriteFile.PluginDirectoryWrite -- Reviewed compatibility exception: The destination is the explicit wp-content cache/drop-in path, not this plugin directory. Runtime sentinels and owned drop-in rollback must survive plugin upgrades.
     11@file_put_contents($itdna_tc_runtime_dir . 'runtime-disabled.flag', "1\n", LOCK_EX);
     12// phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink -- Reviewed compatibility exception: Cache/runtime local filesystem operation: retain native atomic rename, checked deletion result, permissions or timestamps. Replacing it with remote/copy-based WP_Filesystem operations changes the cache consistency contract.
     13@unlink($itdna_tc_runtime_dir . 'runtime-active.flag');
     14
     15// Uninstall cleanup must never turn the WordPress Plugins delete transaction into a
     16// critical error. Every cleanup below is best-effort and scoped to this plugin.
     17try {
     18
    1519if (!function_exists('WP_Filesystem')) {
    1620    require_once ABSPATH . 'wp-admin/includes/file.php';
    1721}
    1822global $wp_filesystem;
    19 if (WP_Filesystem() && $wp_filesystem && is_dir($itdna_tc_lite_root)) {
    20     $wp_filesystem->rmdir($itdna_tc_lite_root, true);
    21 }
     23WP_Filesystem();
     24$itdna_tc_fs = is_object($wp_filesystem) ? $wp_filesystem : null;
     25
     26// Cloudflare Workers deletion is ownership-scoped and best-effort. Plugin-owned
     27// Workers only; NEVER delete WordPress uploads, another Worker or an R2 bucket.
     28// Run BEFORE options containing encrypted tokens/ownership records are purged.
     29try {
     30    require_once __DIR__ . '/includes/class-itdna-workers-assets.php';
     31    ITDNA_Workers_Assets::uninstall_cleanup();
     32} catch (Throwable $itdna_tc_remote_uninstall_error) {
     33    // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Reviewed compatibility exception: Production failure diagnostics are intentional and do not render to visitors. Removing this logging would remove failure visibility.
     34    error_log('[ITDNA Turbo Cache] Remote Worker uninstall cleanup did not complete.');
     35}
     36
     37// Remove ONLY cryptographically verified derivatives recorded when this plugin
     38// actually generated them. No filename-only scans and no WordPress originals.
     39// A time-bounded uninstall cannot delete an arbitrarily large media library;
     40// any remaining or unverified files are preserved rather than risk data loss.
     41require_once __DIR__ . '/includes/class-itdna-generated-image-registry.php';
     42$itdna_tc_media_cleanup = ITDNA_Generated_Image_Registry::cleanup(2500, 8.0);
     43
     44// Remove our advanced-cache.php only if it is definitely ours.
     45$itdna_tc_dropin = WP_CONTENT_DIR . '/advanced-cache.php';
     46if ($itdna_tc_fs && $itdna_tc_fs->is_file($itdna_tc_dropin)) {
     47    $itdna_tc_head = $itdna_tc_fs->get_contents($itdna_tc_dropin);
     48    if (is_string($itdna_tc_head) && false !== strpos(substr($itdna_tc_head, 0, 512), 'IndiaTVDNA Turbo Cache Early Drop-in')) {
     49        $itdna_tc_fs->delete($itdna_tc_dropin, false, 'f');
     50    }
     51}
     52
     53// Remove our object-cache.php only if it is definitely ours. Fail closed first:
     54// if host permissions refuse deletion, the orphaned drop-in must not keep Redis/
     55// Memcached persistence active after the plugin itself is gone.
     56$itdna_tc_object_dropin = WP_CONTENT_DIR . '/object-cache.php';
     57if ($itdna_tc_fs && $itdna_tc_fs->is_file($itdna_tc_object_dropin)) {
     58    $itdna_tc_head = $itdna_tc_fs->get_contents($itdna_tc_object_dropin);
     59    if (is_string($itdna_tc_head) && false !== strpos(substr($itdna_tc_head, 0, 768), 'IndiaTVDNA Turbo Cache Object Cache Drop-in')) {
     60        $itdna_tc_cfg_dir = WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache/';
     61        if (!$itdna_tc_fs->is_dir($itdna_tc_cfg_dir)) { $itdna_tc_fs->mkdir($itdna_tc_cfg_dir, 0755, true); }
     62        $itdna_tc_cfg = $itdna_tc_cfg_dir . 'object-cache-config.php';
     63        $itdna_tc_disabled = "<?php\nreturn array('disabled'=>true,'backend'=>'auto','resolved_backend'=>'','non_persistent_groups'=>array('counts','plugins','options','site-options','theme_json'));\n";
     64        if ($itdna_tc_fs->is_dir($itdna_tc_cfg_dir)) { $itdna_tc_fs->put_contents($itdna_tc_cfg, $itdna_tc_disabled, defined('FS_CHMOD_FILE') ? FS_CHMOD_FILE : 0640); }
     65        $itdna_tc_fs->delete($itdna_tc_object_dropin, false, 'f');
     66    }
     67}
     68
     69// Restore/remove only the WP_CACHE line that this plugin previously managed.
     70// If another active cache plugin/drop-in now needs WP_CACHE, preserve a generic true
     71// define instead of removing it and breaking the foreign cache owner.
     72$itdna_tc_config = is_file(ABSPATH . 'wp-config.php') ? ABSPATH . 'wp-config.php' : dirname(rtrim(ABSPATH, '/\\')) . '/wp-config.php';
     73$itdna_tc_foreign_advanced = false;
     74if ($itdna_tc_fs && $itdna_tc_fs->is_file(WP_CONTENT_DIR . '/advanced-cache.php')) {
     75    $itdna_tc_foreign_head = $itdna_tc_fs->get_contents(WP_CONTENT_DIR . '/advanced-cache.php');
     76    $itdna_tc_foreign_advanced = !(is_string($itdna_tc_foreign_head) && false !== strpos(substr($itdna_tc_foreign_head, 0, 512), 'IndiaTVDNA Turbo Cache Early Drop-in'));
     77}
     78$itdna_tc_active_plugins = (array) get_option('active_plugins', array());
     79if (is_multisite()) { $itdna_tc_active_plugins = array_merge($itdna_tc_active_plugins, array_keys((array)get_site_option('active_sitewide_plugins', array()))); }
     80$itdna_tc_cache_plugins = array(
     81    'litespeed-cache/litespeed-cache.php','wp-rocket/wp-rocket.php','w3-total-cache/w3-total-cache.php','wp-super-cache/wp-cache.php',
     82    'sg-cachepress/sg-cachepress.php','wp-optimize/wp-optimize.php','breeze/breeze.php','hummingbird-performance/wp-hummingbird.php'
     83);
     84$itdna_tc_foreign_cache_active = $itdna_tc_foreign_advanced || (bool)array_intersect($itdna_tc_cache_plugins, $itdna_tc_active_plugins);
     85if ($itdna_tc_fs && $itdna_tc_fs->is_file($itdna_tc_config) && $itdna_tc_fs->is_writable($itdna_tc_config)) {
     86    $itdna_tc_data = $itdna_tc_fs->get_contents($itdna_tc_config);
     87    if (is_string($itdna_tc_data)) {
     88        $itdna_tc_before = $itdna_tc_data;
     89        $itdna_tc_original = get_option('itdna_tc_wp_cache_original', '');
     90        if ($itdna_tc_original) {
     91            $itdna_tc_data = preg_replace("/^define\\('WP_CACHE', true\\); \\/\\/ IndiaTVDNA Turbo Cache\\s*$/m", $itdna_tc_original, $itdna_tc_data, 1);
     92        } elseif (get_option('itdna_tc_wp_cache_inserted')) {
     93            if ($itdna_tc_foreign_cache_active) {
     94                $itdna_tc_data = preg_replace("/^define\\('WP_CACHE', true\\); \\/\\/ IndiaTVDNA Turbo Cache\\s*$/m", "define('WP_CACHE', true); // Preserved for active cache drop-in", $itdna_tc_data, 1);
     95            } else {
     96                $itdna_tc_data = preg_replace("/^define\\('WP_CACHE', true\\); \\/\\/ IndiaTVDNA Turbo Cache\\s*$/m", '', $itdna_tc_data, 1);
     97            }
     98        }
     99        if ($itdna_tc_data !== $itdna_tc_before) {
     100            $itdna_tc_tmp = $itdna_tc_config . '.itdna-tmp';
     101            if ($itdna_tc_fs->put_contents($itdna_tc_tmp, $itdna_tc_data, defined('FS_CHMOD_FILE') ? FS_CHMOD_FILE : 0644)) {
     102                if (!$itdna_tc_fs->move($itdna_tc_tmp, $itdna_tc_config, true)) { $itdna_tc_fs->delete($itdna_tc_tmp, false, 'f'); }
     103            }
     104        }
     105    }
     106}
     107
     108foreach (array(
     109    'itdna_tc_scheduler_settings','itdna_tc_strict_event_gate_state','itdna_tc_heavy_worker_lock_1','itdna_tc_heavy_worker_lock_2','itdna_tc_heavy_worker_lock_3',
     110    'itdna_tc_options','itdna_tc_options_schema_version','itdna_tc_activated_at','itdna_tc_last_purge','itdna_tc_last_preload',
     111    'itdna_tc_preload_page','itdna_tc_preload_queue','itdna_tc_preload_queue_built','itdna_tc_preload_cursor','itdna_tc_preload_status','itdna_tc_last_cf_purge','itdna_tc_cf_connection_status','itdna_tc_cf_edge_status','itdna_tc_cf_edge_warm_queue','itdna_tc_cf_edge_warm_status','itdna_tc_cf_live_probe','itdna_tc_cf_smart_audit','itdna_tc_cdn_health','itdna_tc_last_db_cleanup','itdna_tc_last_db_report','itdna_tc_db_cleanup_lock','itdna_tc_early_status','itdna_tc_last_self_test','itdna_tc_self_test_v2_progress','itdna_tc_self_test_http_block_cooldown_until',
     112    'itdna_tc_wp_cache_original','itdna_tc_wp_cache_inserted','itdna_tc_google_fonts_map','itdna_tc_last_cache_gc','itdna_tc_last_auto_fix','itdna_tc_last_url_inspection','itdna_tc_google_fonts_built','itdna_tc_object_cache_installed','itdna_tc_version',
     113    'itdna_tc_priority_urls','itdna_tc_priority_preload_status','itdna_tc_preload_failures','itdna_tc_preload_lock','itdna_tc_preload_adaptive_state','itdna_tc_preload_queue_meta','itdna_tc_last_selective_purge','itdna_tc_compatibility_scan','itdna_tc_last_health_report','itdna_tc_auto_diagnostics_report','itdna_tc_self_heal_history','itdna_tc_self_heal_cooldowns','itdna_tc_self_heal_safe_snapshot','itdna_tc_self_heal_safe_mode','itdna_tc_last_settings_snapshot','itdna_tc_upgrade_needs_purge',
     114    'itdna_tc_auto_v20_job','itdna_tc_auto_v20_snapshot','itdna_tc_last_auto_site_apply','itdna_tc_performance_scan','itdna_tc_automatic_benchmark_scan','itdna_tc_preconnect_snapshot','itdna_tc_site_profile',
     115    'itdna_tc_image_queue','itdna_tc_image_stats','itdna_tc_image_scan','itdna_tc_image_status','itdna_tc_image_failures','itdna_tc_image_variant_manifest','itdna_tc_image_worker_lock','itdna_tc_real_image_pool_state','itdna_tc_real_image_pool_auto','itdna_tc_image_rebuild_after','itdna_tc_object_cache_detection','itdna_tc_gravatar_queue','itdna_tc_gravatar_manifest','itdna_tc_gravatar_status','itdna_tc_asset_warm_status','itdna_tc_v252_repair','itdna_tc_asset_dirty',
     116    'itdna_tc_admin_refresh_notice','itdna_tc_asset_build_report','itdna_tc_css_delivery_map','itdna_tc_css_viewport_learning','itdna_tc_css_template_learning','itdna_tc_css_runtime_guard','itdna_tc_asset_retry_state','itdna_tc_asset_retry_after','itdna_tc_metrics_reset_at','itdna_tc_object_cache_upgrade_sync_error','itdna_tc_upgrade_sync_object_cache','itdna_tc_activation_reinstall_object_cache','itdna_tc_object_cache_activation_reinstall_error',
     117    'itdna_tc_background_governor_status','itdna_tc_background_health_status','itdna_tc_heavy_worker_lock','itdna_tc_tag_index_started_at','itdna_tc_environment_maintenance_pending','itdna_tc_object_cache_deactivate_notice','itdna_tc_cf_deactivate_cleanup_notice',
     118    'itdna_tc_cf_purge_queue','itdna_tc_cache_delivery_repair_status','itdna_tc_install_bootstrap_complete','itdna_tc_install_bootstrap_lock','itdna_tc_install_bootstrap_pending','itdna_tc_install_bootstrap_status','itdna_tc_green_soft_rollout','itdna_tc_adaptive_all_on_upgrade','itdna_tc_last_scheduled_purge','itdna_tc_last_regression_report','itdna_tc_db_schedule_cursor','itdna_tc_db_continue_passes'
     119) as $itdna_tc_opt) { delete_option($itdna_tc_opt); }
     120
     121// These three runtime locks/ticks are transients, not normal options. delete_option()
     122// does not remove the _transient_* rows, so clear them through the proper API.
     123delete_transient('itdna_tc_asset_spawn_lock');
     124
     125delete_option('itdna_tc_lcp_learning');
     126delete_option('itdna_tc_lcp_template_learning');
     127delete_transient('itdna_tc_image_spawn_lock');
     128delete_transient('itdna_tc_image_admin_tick');
     129delete_transient('itdna_tc_image_pressure_streak');
     130delete_transient('itdna_tc_preload_pressure_streak');
     131delete_transient('itdna_tc_priority_preload_pressure_streak');
     132delete_transient('itdna_tc_db_health_snapshot');
     133delete_transient('itdna_tc_background_governor_sample');
     134delete_transient('itdna_tc_background_governor_db_sample');
     135delete_transient('itdna_tc_resource_disk_benchmark');
     136delete_transient('itdna_tc_cgroup_cpu_stat_prev');
     137delete_transient('itdna_tc_live_cpu_sample_v151');
     138delete_transient('itdna_tc_cache_delivery_repair_check');
     139delete_transient('itdna_tc_cron_runtime_check');
     140delete_transient('itdna_tc_asset_bootstrap_check');
     141delete_transient('itdna_tc_green_rollout_cooldown');
     142
     143wp_clear_scheduled_hook('itdna_tc_preload_event');
     144wp_clear_scheduled_hook('itdna_tc_preload_continue_event');
     145wp_clear_scheduled_hook('itdna_tc_priority_preload_event');
     146wp_clear_scheduled_hook('itdna_tc_cache_gc_event');
     147wp_clear_scheduled_hook('itdna_tc_cache_gc_retry_event');
     148wp_clear_scheduled_hook('itdna_tc_cache_index_reconcile_event');
     149wp_clear_scheduled_hook('itdna_tc_tag_index_rebuild_event');
     150wp_clear_scheduled_hook('itdna_tc_db_cleanup_event');
     151wp_clear_scheduled_hook('itdna_tc_db_cleanup_retry_event');
     152wp_clear_scheduled_hook('itdna_tc_health_event');
     153wp_clear_scheduled_hook('itdna_tc_health_retry_event');
     154wp_clear_scheduled_hook('itdna_tc_first_install_bootstrap_event');
     155wp_clear_scheduled_hook('itdna_tc_easy_setup_event');
     156wp_clear_scheduled_hook('itdna_tc_cache_delivery_repair_event');
     157wp_clear_scheduled_hook('itdna_tc_system_maintenance_event');
     158wp_clear_scheduled_hook('itdna_tc_ownership_refresh_event');
     159wp_clear_scheduled_hook('itdna_tc_runtime_plan_rebuild_event');
     160wp_clear_scheduled_hook('itdna_tc_cf_purge_event');
     161wp_clear_scheduled_hook('itdna_tc_litespeed_purge_event');
     162wp_clear_scheduled_hook('itdna_tc_scheduled_purge_event');
     163wp_clear_scheduled_hook('itdna_tc_scheduled_purge_event_retry');
     164wp_clear_scheduled_hook('itdna_tc_regression_event');
     165wp_clear_scheduled_hook('itdna_tc_runner_watchdog');
     166wp_clear_scheduled_hook('itdna_tc_edge_tag_purge_event');
     167
     168delete_option('itdna_tc_auto_step_lock');
     169delete_option('itdna_tc_server_profile_snapshot');
     170delete_option('itdna_tc_server_profile_apply');
     171delete_option('itdna_tc_server_profile_status');
     172delete_option('itdna_tc_server_profile_lock');
     173
     174delete_option('itdna_tc_preload_last_queue_after_purge');
     175
     176wp_clear_scheduled_hook('itdna_tc_cf_edge_warm_event');
     177wp_clear_scheduled_hook('itdna_tc_image_event');
     178wp_clear_scheduled_hook('itdna_tc_image_fast_event');
     179wp_clear_scheduled_hook('itdna_tc_gravatar_event');
     180wp_clear_scheduled_hook('itdna_tc_asset_warm_event');
     181wp_clear_scheduled_hook('itdna_tc_asset_auto_event');
     182wp_clear_scheduled_hook('itdna_tc_external_asset_worker');
     183
     184// Original uploads and all unverified/legacy derivatives are retained.
     185
     186// Future-proof cleanup: this prefix belongs exclusively to this plugin. Remove any
     187// runtime option/transient introduced by a newer build even if an old explicit list
     188// did not know its name yet.
     189global $wpdb;
     190$itdna_tc_like_option = $wpdb->esc_like('itdna_tc_') . '%';
     191$itdna_tc_like_transient = $wpdb->esc_like('_transient_itdna_tc_') . '%';
     192$itdna_tc_like_timeout = $wpdb->esc_like('_transient_timeout_itdna_tc_') . '%';
     193// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- uninstall owns and removes only plugin-prefixed rows.
     194$itdna_tc_owned_names = $wpdb->get_col($wpdb->prepare("SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s OR option_name LIKE %s", $itdna_tc_like_option, $itdna_tc_like_transient, $itdna_tc_like_timeout));
     195foreach ((array)$itdna_tc_owned_names as $itdna_tc_owned_name) { delete_option((string)$itdna_tc_owned_name); }
     196
     197// v1.3.22 dedicated scale tables are plugin-owned and safe to remove on uninstall.
     198foreach (array('itdna_tc_queue','itdna_tc_metrics','itdna_tc_edge_tags','itdna_tc_r2_mirror') as $itdna_tc_table_suffix) {
     199    $itdna_tc_table = $wpdb->prefix . $itdna_tc_table_suffix;
     200    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- uninstall removes only plugin-owned tables. Reviewed compatibility exception: Plugin-owned queue/mirror/schema records or current database maintenance diagnostics have no equivalent WordPress object API. Prepared SQL/typed wpdb writes are retained; cached results could serve stale work or stale delivery evidence.
     201    $wpdb->query($wpdb->prepare('DROP TABLE IF EXISTS %i', $itdna_tc_table));
     202}
     203
     204// Public REST cache fallback transients intentionally use a shorter key prefix so
     205// WordPress's 172-character transient key ceiling still leaves room for hashes.
     206$itdna_tc_rest_like = $wpdb->esc_like('_transient_itdna_r_') . '%';
     207$itdna_tc_rest_timeout_like = $wpdb->esc_like('_transient_timeout_itdna_r_') . '%';
     208// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- uninstall cleanup is prefix-scoped to this plugin.
     209$itdna_tc_rest_names = $wpdb->get_col($wpdb->prepare("SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", $itdna_tc_rest_like, $itdna_tc_rest_timeout_like));
     210foreach ((array)$itdna_tc_rest_names as $itdna_tc_rest_name) { delete_option((string)$itdna_tc_rest_name); }
     211
     212// Uninstall must REMOVE plugin-generated cache, not just rename it forever.
     213// Retire runtime first (already disabled above), then quarantine the owned cache
     214// directory to prevent old early-cache requests from using it during cleanup.
     215// The cleaner refuses unverified folders, uploads, images and unrecognized files.
     216// A bounded pass prevents huge caches from causing a WordPress uninstall timeout.
     217require_once __DIR__ . '/includes/class-itdna-orphan-cache-cleaner.php';
     218$itdna_tc_dir = WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache';
     219$itdna_tc_archive = '';
     220if (is_dir($itdna_tc_dir) && !is_link($itdna_tc_dir)) {
     221    for ($itdna_tc_idx = 0; $itdna_tc_idx < 10; ++$itdna_tc_idx) {
     222        $itdna_tc_suffix = gmdate('YmdHis') . ($itdna_tc_idx ? '-' . $itdna_tc_idx : '');
     223        $itdna_tc_candidate = WP_CONTENT_DIR . '/cache/indiatvdna-turbo-cache-uninstalled-' . $itdna_tc_suffix;
     224        if (file_exists($itdna_tc_candidate)) { continue; }
     225        // phpcs:ignore PluginCheck.CodeAnalysis.WriteFile.PluginDirectoryWrite,WordPress.WP.AlternativeFunctions.rename_rename -- Reviewed compatibility exception: Cache/runtime local filesystem operation: retain native atomic rename, checked deletion result, permissions or timestamps. Replacing it with remote/copy-based WP_Filesystem operations changes the cache consistency contract. The destination is the explicit wp-content cache/drop-in path, not this plugin directory. Runtime sentinels and owned drop-in rollback must survive plugin upgrades.
     226        if (@rename($itdna_tc_dir, $itdna_tc_candidate)) { $itdna_tc_archive = $itdna_tc_candidate; break; }
     227    }
     228}
     229// Old archives are processed too, within ONE total request budget. This only
     230// cleans verified cache-format files; non-cache or recoverable media are kept.
     231try {
     232    $itdna_tc_cleanup_start = microtime(true);
     233    // Remove the current installation's cache FIRST, before old archived data
     234    // can consume the request's time budget.
     235    if ($itdna_tc_archive !== '') {
     236        $itdna_tc_primary = ITDNA_Orphan_Cache_Cleaner::prune($itdna_tc_archive, 18000, 9.0);
     237    }
     238    $itdna_tc_cleanup = ITDNA_Orphan_Cache_Cleaner::prune_archives(
     239        20000, max(0.1, 12.0 - (microtime(true) - $itdna_tc_cleanup_start))
     240    );
     241    if ($itdna_tc_archive === '' && is_dir($itdna_tc_dir)) {
     242        // Rename was denied. The active path is safe to clean only when the
     243        // plugin's disabled marker proves the directory is no longer active.
     244        $itdna_tc_cleanup_active = ITDNA_Orphan_Cache_Cleaner::prune($itdna_tc_dir, 3000, 2.0, true);
     245    }
     246    if (!empty($itdna_tc_cleanup['remaining']) || !empty($itdna_tc_cleanup['protected'])) {
     247        // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Reviewed compatibility exception: Production failure diagnostics are intentional and do not render to visitors. Removing this logging would remove failure visibility.
     248        error_log('[IndiaTVDNA Turbo Cache] Uninstall left protected/large cache archives for manual review. Original uploads were not touched by cache cleanup.');
     249    }
     250} catch (Throwable $itdna_tc_cache_cleanup_error) {
     251    // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Reviewed compatibility exception: Production failure diagnostics are intentional and do not render to visitors. Removing this logging would remove failure visibility.
     252    error_log('[IndiaTVDNA Turbo Cache] Safe cache cleanup could not finish; no non-cache files were targeted.');
     253}
     254
     255
     256if (!function_exists('insert_with_markers')) {
     257    require_once ABSPATH . 'wp-admin/includes/misc.php';
     258}
     259$itdna_tc_ht = ABSPATH . '.htaccess';
     260if ($itdna_tc_fs && $itdna_tc_fs->exists($itdna_tc_ht) && $itdna_tc_fs->is_writable($itdna_tc_ht)) {
     261    insert_with_markers($itdna_tc_ht, 'IndiaTVDNA Turbo Cache', array());
     262}
     263
     264delete_option('itdna_tc_master_enabled');
     265delete_option('itdna_tc_master_runtime_snapshot');
     266delete_option('itdna_tc_coexistence_asset_blacklist');
     267
     268// Low-load diagnostic journal (privacy-safe event ring).
     269delete_option('itdna_tc_diagnostic_journal');
     270
     271} catch (Throwable $itdna_tc_uninstall_error) {
     272    // Intentionally swallow cleanup failures. WordPress must be allowed to remove the
     273    // plugin directory; fail-closed sentinels/owner checks make leftover cache files inert.
     274}
     275
     276delete_option('itdna_tc_benchmark_lab_report');
     277delete_option('itdna_tc_rollback_history');
     278delete_option('itdna_tc_last_known_good');
     279delete_option('itdna_tc_change_impact_events');
     280delete_option('itdna_tc_change_impact_last_probe');
     281delete_option('itdna_tc_central_dependency_queue_history');
     282delete_option('itdna_tc_intelligence_suite_v1318');
     283delete_option('itdna_tc_performance_extensions_v1320');
     284wp_clear_scheduled_hook('itdna_tc_change_impact_probe');
Note: See TracChangeset for help on using the changeset viewer.