/* Product direction: quiet surfaces, compact controls, clear operational hierarchy. */
:root {
 --surface:#151a23; --surface-soft:#1b2230; --workspace:#0e1219; --ink:#edf1f7; --ink-secondary:#a3aebe;
 --stroke:#2b3443; --accent:#818cf8; --accent-soft:#252c47; --nav-surface:#11161f;
 --bg:var(--workspace); --bg-2:var(--workspace); --panel:var(--surface); --panel-2:var(--surface-soft);
 --text:var(--ink); --text-strong:var(--ink); --muted:var(--ink-secondary); --muted-2:var(--ink-secondary); --line:var(--stroke);
 --shadow:0 2px 6px #00000012; --input-bg:var(--surface); --input-text:var(--ink);
}
html,body { background:var(--workspace)!important; color:var(--ink); }
body::before,.admin-shell::before,.admin-main::before,.sidebar::before,.sidebar::after { display:none!important; }
.sidebar,.admin-sidebar { background:var(--nav-surface)!important; border-right:1px solid var(--stroke); box-shadow:none!important; backdrop-filter:none; }
.sidebar .brand,.admin-brand strong { color:var(--ink)!important; background:none!important; -webkit-text-fill-color:var(--ink); }
.sidebar .brand small,.admin-brand small { color:var(--ink-secondary)!important; letter-spacing:.1em; font-size:9px; }
.sidebar .nav-item,.admin-nav { color:var(--ink-secondary)!important; border:1px solid transparent!important; border-radius:7px; font-size:13px; min-height:41px; box-shadow:none!important; }
.sidebar .nav-item.active,.admin-nav.active { background:var(--accent-soft)!important; color:var(--accent)!important; font-weight:600; }
.sidebar .nav-item:hover,.admin-nav:hover { background:var(--surface-soft)!important; }
.sidebar .nav-item b,.admin-nav>span { background:transparent!important; border:0!important; color:inherit!important; box-shadow:none!important; }
.sidebar .nav-label,.menu-label { color:var(--ink-secondary)!important; font-size:10px; letter-spacing:.1em; }
.sidebar .theme-switch,.sidebar-bottom a { color:var(--ink-secondary)!important; }
.sidebar .theme-switch button[aria-pressed="true"] { background:var(--accent-soft)!important; color:var(--accent)!important; }
.topbar { background:var(--workspace)!important; border-color:var(--stroke); backdrop-filter:none; min-height:72px; }
.topbar h1 { color:var(--ink); font-size:16px; font-weight:600; }
.topbar p,.admin-breadcrumb { font-size:12px; color:var(--ink-secondary)!important; }
.top-actions,.admin-top-actions { flex-wrap:wrap; gap:8px; }
.admin-topbar { min-height:90px; padding:20px 0; }
.admin-topbar h1 { font-size:24px; background:none!important; color:var(--ink)!important; -webkit-text-fill-color:var(--ink); }
.admin-topbar::after { display:none; }
.page-heading h2,.noc-heading h2 { font-size:24px; font-weight:600; letter-spacing:-.035em; background:none; color:var(--ink); }
.noc-heading h2 em { color:var(--ink)!important; font-style:normal; }
.page-heading p,.noc-heading p { color:var(--ink-secondary); }
.eyebrow,.platform-kicker,.panel-kicker { color:var(--ink-secondary)!important; letter-spacing:.08em; font-size:10px; }
:is(.metric,.panel,.site-card,.solution-group,.solution-card,.health-overview,.forecast-panel,.fleet-inventory,.solution-map,.activity-panel,.admin-welcome,.admin-user,.guide-paper,.guide-side,.filters) {
 background:var(--surface)!important; border-color:var(--stroke)!important; border-radius:12px; box-shadow:var(--shadow)!important;
}
.metric { min-height:106px; padding:17px; position:relative; }
.metric strong { font-size:28px; font-weight:600; letter-spacing:-.04em; }
.metric p { font-size:11px!important; color:var(--ink-secondary)!important; }
.metric-icon { background:var(--surface-soft)!important; border:0!important; box-shadow:none!important; }
.metric::after,.admin-welcome::after { display:none!important; }
.solution-head,.solution-group>header,.overview-panel-head,.panel-head { background:transparent!important; border-bottom:1px solid var(--stroke); }
.solution-head strong { font-size:15px; font-weight:600; }
.company-divider { background:none!important; color:var(--ink-secondary); font-size:10px; letter-spacing:.05em; }
details.site-row>summary { padding-top:15px; padding-bottom:15px; background:transparent!important; }
details.site-row[open]>summary { background:var(--surface-soft)!important; }
.site-row-detail { background:transparent!important; }
:is(.data-table,.table-wrap,table) { border-color:var(--stroke); }
th { background:var(--surface-soft)!important; color:var(--ink-secondary)!important; font-weight:500; }
td { border-color:var(--stroke)!important; }
tbody tr:hover { background:var(--surface-soft); }
:is(.btn,.icon-btn,.row-button,.admin-theme-switch,.theme-switch) { border-color:var(--stroke); border-radius:7px; box-shadow:none; }
.btn.primary,.primary-button,.auth-panel button[type="submit"] { background:#4f46e5!important; border-color:#4f46e5!important; color:#fff!important; box-shadow:0 1px 2px #00000014!important; border-radius:7px; }
.btn.primary:hover,.primary-button:hover,.auth-panel button[type="submit"]:hover { background:#4338ca!important; }
:is(input,select,textarea) { background:var(--surface)!important; border-color:var(--stroke)!important; color:var(--ink)!important; border-radius:7px; font-size:13px; }
:is(input,select,textarea):focus { outline:2px solid var(--accent)!important; outline-offset:2px; }
:is(button,a,summary):focus-visible { outline:2px solid var(--accent)!important; outline-offset:3px; }
.language-switch { display:inline-flex; align-items:center; flex-shrink:0; gap:2px; padding:3px; border:1px solid var(--stroke); border-radius:7px; background:var(--surface); }
.language-switch button { border:0; padding:5px 8px; min-height:28px; background:transparent; color:var(--ink-secondary); border-radius:4px; font-size:12px; cursor:pointer; }
.language-switch button[aria-pressed="true"] { background:var(--accent-soft); color:var(--accent); font-weight:600; }
.auth-tools { display:flex; justify-content:flex-end; align-items:center; gap:8px; margin-bottom:28px; }
.auth-theme-button { min-width:36px; min-height:36px; border:1px solid var(--stroke); border-radius:7px; background:var(--surface); color:var(--ink-secondary); cursor:pointer; }
body:has(.auth-shell) { padding:24px; min-height:100dvh; background:radial-gradient(at 90% 10%,#0ea5e914,transparent 45%),radial-gradient(at 5% 90%,#6366f114,transparent 40%),var(--workspace)!important; }
.auth-shell { width:min(1200px,100%); min-height:700px; grid-template-columns:1.05fr 1fr; border:1px solid #22445a; border-radius:24px; background:var(--surface); box-shadow:0 30px 100px #00000035; }
.auth-hero { padding:42px; background:linear-gradient(#7dd3fc09 1px,transparent 1px),linear-gradient(90deg,#7dd3fc09 1px,transparent 1px),radial-gradient(ellipse at 80% 30%,#087da32b,transparent 55%),linear-gradient(150deg,#06111f,#0b2137 65%,#061725)!important; background-size:42px 42px,42px 42px,auto,auto!important; border:0; color:#f2f4fa; }
.auth-hero::before,.auth-hero::after,.hero-network,.backup-animation { display:block!important; }
.auth-hero .brand { font-size:16px; font-weight:600; }
.auth-hero .brand-copy small { color:#a2acc5; }
.auth-hero .brand-mark { background:radial-gradient(at 70% 20%,#3b82f64d,transparent),#091c2d; border-color:#24758c; border-radius:12px; }
.auth-hero .hero-body { margin:auto 0 0; padding:170px 0 8px; }
.auth-hero .hero-tag { color:#adb6d0; font-size:11px; letter-spacing:.12em; margin:0 0 20px; }
.auth-hero h1 { font-size:clamp(27px,3.2vw,42px); line-height:1.35; letter-spacing:0; font-weight:650; margin:0 0 20px; color:#f2f4fa; word-break:normal; overflow-wrap:normal; text-wrap:wrap; }
.auth-hero h1 .hero-title-line { display:block; white-space:nowrap; }
.auth-hero h1 .hero-title-line:last-child { color:#50ddef; }
.auth-hero h1 em { display:none; }
.auth-hero .hero-body>p:last-child { max-width:370px; font-size:14px; line-height:1.8; color:#b1bad0; }
.auth-hero .live-chip { display:table; margin-bottom:14px; color:#b1f2f7; background:#092d3ba8; }
.auth-hero .live-chip i { display:inline-block; margin-right:7px; }
.auth-capabilities { display:flex; flex-wrap:wrap; gap:8px; margin-top:30px; }
.auth-capabilities span { padding:6px 10px; color:#c1c8dc; border:1px solid #38405a; border-radius:6px; font-size:11px; }
.auth-footnote { color:#a3aec7; font-size:11px; padding-top:25px; border-top:1px solid #343b52; }
.auth-panel { padding:30px 44px 36px; background:linear-gradient(155deg,#0d1b2d,#06111e)!important; display:flex; flex-direction:column; justify-content:center; }
:root[data-theme="light"] .auth-panel { background:linear-gradient(155deg,#ffffff,#eef5fb)!important; }
.auth-panel h2 { font-size:27px; font-weight:600; letter-spacing:-.035em; margin:18px 0 8px; color:var(--ink)!important; }
.auth-panel>.muted { color:var(--ink-secondary)!important; font-size:13px; line-height:1.7; min-height:44px; }
.auth-panel>.eyebrow { display:none; }
.auth-panel .mode-tabs { border:1px solid var(--stroke); background:var(--surface-soft); padding:4px; border-radius:8px; margin-bottom:10px; }
.auth-panel .mode-tabs button { font-size:12px; color:var(--ink-secondary); background:none; border:0; border-radius:5px; padding:9px; box-shadow:none; }
.auth-panel .mode-tabs button[aria-selected="true"] { color:#fff; background:linear-gradient(135deg,#1480da,#3569ed)!important; box-shadow:0 4px 14px #2786ef33; }
.auth-panel .field { margin:18px 0; }
.auth-panel label { font-size:12px; font-weight:500; color:var(--ink)!important; }
.auth-panel input { min-height:44px; padding:11px 13px; }
.auth-panel button[type="submit"] { min-height:48px; font-size:14px; font-weight:600; margin-top:8px; background:linear-gradient(105deg,#087fc4,#146fc7 55%,#485bea)!important; background-size:180% 100%!important; border:0!important; border-radius:10px; }
.auth-panel .security-note { color:var(--ink-secondary)!important; background:none!important; border:0; border-top:1px solid var(--stroke); padding:20px 0 0; font-size:11px; line-height:1.7; margin-top:22px; }
.auth-panel .message { font-size:12px; }
.auth-panel .local-bypass { font-size:11px; min-height:32px; color:var(--accent)!important; border-color:var(--stroke)!important; background:var(--accent-soft)!important; }
.auth-panel,.auth-panel input,.auth-panel .mode-tabs { box-shadow:none!important; }
.auth-panel>.local-test-switcher.in-header { position:static; align-self:flex-end; margin:0 0 16px; }
.auth-panel::after { display:block; pointer-events:none; }
.auth-hero .backup-animation { opacity:.45; }
:lang(th) :is(h1,h2,h3,p,label,.eyebrow,.panel-kicker,.hero-tag) { word-break:normal; overflow-wrap:normal; letter-spacing:normal; }
:lang(th) :is(th,td) { word-break:normal; overflow-wrap:break-word; letter-spacing:0; }
.dialog-head { flex-wrap:wrap; gap:12px; }
.dialog-head>.language-switch { order:2; margin-left:auto; }
.dialog-head>.close-button { order:3; }
dialog,.modal-card { background:var(--surface)!important; color:var(--ink)!important; border:1px solid var(--stroke)!important; border-radius:14px; box-shadow:0 24px 80px #00000030; }
.metric-top { flex-wrap:nowrap; }
.metric-top p { min-width:0; flex:1; }
.metric-icon { flex-shrink:0; width:25px; height:25px; }
.card,.ops-health-panel,.ops-forecast { background:var(--surface)!important; border-color:var(--stroke)!important; box-shadow:var(--shadow)!important; }
.noc-heading { border:0; padding-bottom:0; }
.noc-heading h2 { font-style:normal; }
.fleet-name strong,.fleet-name span { white-space:normal; overflow-wrap:anywhere; }
.overview-panel::after { display:none!important; }
.fleet-table-head,.fleet-table-row { grid-template-columns:minmax(160px,1.5fr) 72px minmax(100px,.8fr) 68px; }
.fleet-table-head { letter-spacing:0; font-size:11px; }
.sidebar-foot.mobile-account-controls { display:flex; flex-wrap:wrap; align-items:center; gap:8px; grid-column:1/-1; flex-basis:100%; width:100%; margin:0; padding:8px 0 0; border:0; }
.mobile-account-controls .theme-switch { padding:3px 5px; margin-left:auto; background:var(--surface)!important; border-color:var(--stroke)!important; color:var(--ink-secondary)!important; }
.mobile-account-controls .theme-switch>span { display:none; }
.mobile-account-controls .logout-btn { width:auto; min-height:34px; padding:6px 10px; background:var(--surface)!important; border-color:var(--stroke)!important; font-size:12px; }
@media(max-width:1100px) {
 .admin-view td[data-label]::before,.jobs-table td[data-label]::before { content:attr(data-label)!important; color:var(--ink-secondary); text-transform:none; font-size:11px; letter-spacing:0; }
 .admin-view td[colspan]::before { content:none!important; }
}
@media(max-width:760px) {
 body:has(.auth-shell) { padding:16px; }
 .auth-shell { grid-template-columns:1fr; min-height:0; max-width:460px; }
 .auth-hero { padding:24px; min-height:220px; }
 .auth-hero .hero-body { padding:22px 0 0; margin:0; }
 .auth-hero h1 { font-size:clamp(22px,6.3vw,29px); margin:0; }
 .auth-hero .hero-tag,.auth-hero .hero-body>p:last-child,.auth-capabilities,.auth-footnote { display:none; }
 .auth-panel { padding:22px 24px 28px; }
 .auth-tools { margin-bottom:18px; }
 .topbar { flex-wrap:wrap; gap:10px; }
 .top-actions { margin-left:auto; }
 .language-switch button { padding:4px 6px; }
 .admin-top-actions { gap:6px; }
 .admin-topbar { flex-direction:column; align-items:stretch; gap:14px; }
 .admin-topbar h1 { font-size:22px; }
 .fleet-table-head,.fleet-table-row { grid-template-columns:minmax(0,1fr) 64px 75px; gap:8px; }
 .admin-top-actions { justify-content:flex-start; }
 .secure-chip { display:none; }
 .page-heading h2,.noc-heading h2 { font-size:22px; }
}
/* Single line, ellipsis-truncated to whatever width the column/cell actually
   has -- a later "no horizontal scroll anywhere" redesign pass (admin-pro.css)
   turned off .table-wrap's scroll, which this rule used to rely on as its
   release valve for long names (width:max-content + overflow:visible).
   Without scrolling, that just let the name bleed past its own cell and
   visually overlap the next column instead of ever actually overflowing
   itself -- a long Thai company name at an 18% column width is the common
   case, not an edge case. workspace-experience.js already has a tooltip that
   shows the full name on hover/focus by checking scrollWidth>clientWidth, so
   clipping here (rather than growing the box) is what makes that mechanism
   actually trigger instead of never firing.
   overflow/text-overflow need !important too, not just white-space: this
   class is added by JS to many pre-existing selectors (workspace-experience.js's
   `names` list includes `.activity-site strong`, `.site-card h3`, etc.), some
   of which already declare their own overflow:visible at HIGHER specificity
   than a bare `.record-name` class (e.g. app.css's `.activity-site strong{
   overflow:visible}` beats this class on specificity alone) -- without
   !important here, white-space:nowrap still won (that one already had
   !important) but the clip never applied, so the single-line name just
   overflowed into the next column instead of being clipped (2026-09-07 report:
   GALAXY AUTOMOTIVE COMPANY LIMITED running into the job-name column on the
   dashboard's "Latest Activity" list). */
.record-name { display:block!important; max-width:100%!important; white-space:nowrap!important; overflow:hidden!important; text-overflow:ellipsis!important; line-height:1.6; }
.record-name:focus-visible { outline:2px solid var(--accent); outline-offset:2px; border-radius:3px; }
.record-name-tooltip { position:fixed; z-index:10000; max-width:min(560px,calc(100vw - 24px)); padding:10px 14px; border:1px solid var(--stroke); border-radius:9px; background:var(--surface); color:var(--ink); box-shadow:0 8px 30px #0004; font-size:13px; line-height:1.65; overflow-wrap:anywhere; pointer-events:none; }
.record-name-tooltip[hidden] { display:none; }
.motion-toggle { display:inline-grid; place-items:center; min-width:36px; min-height:36px; padding:5px 8px; border:1px solid var(--stroke); border-radius:7px; background:var(--surface); color:var(--ink-secondary); cursor:pointer; font-size:15px; }
.motion-toggle[aria-pressed="true"] { color:var(--accent); background:var(--accent-soft); }

/* Command-center geometry; the daylight palette lives in light-readability.css. */
.page-content { padding-top:22px; }
.noc-heading { margin-bottom:16px; }
.noc-heading h2 { font-size:clamp(26px,2.4vw,34px); line-height:1.05; letter-spacing:-.045em; }
.noc-heading>div>p:last-child { max-width:72ch; font-size:13px; line-height:1.65; }
.noc-metrics { gap:10px; margin-bottom:12px; }
.noc-metrics .metric {
 min-width:0;
 min-height:88px;
 padding:13px 14px;
 border-radius:10px;
 animation:workspace-card-in .42s cubic-bezier(.2,.8,.2,1) both;
 animation-delay:calc(var(--metric-index,0) * 40ms);
}
.noc-metrics .metric:nth-child(2) { --metric-index:1; }
.noc-metrics .metric:nth-child(3) { --metric-index:2; }
.noc-metrics .metric:nth-child(4) { --metric-index:3; }
.noc-metrics .metric:nth-child(5) { --metric-index:4; }
.noc-metrics .metric:nth-child(6) { --metric-index:5; }
.noc-metrics .metric strong { margin-top:4px; font-size:25px; line-height:1; }
.noc-metrics .metric>span:last-child { display:block; margin-top:7px; font-size:10.5px; line-height:1.3; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.noc-metrics .metric-top p { font-size:10.5px!important; font-weight:600; letter-spacing:.015em; white-space:nowrap; }
.noc-metrics .metric-icon { width:24px; height:24px; font-size:12px; border-radius:7px; }
.ops-health-panel { grid-template-columns:minmax(0,2.55fr) minmax(250px,.85fr); margin-bottom:14px; }
.health-gauges { gap:8px; padding:15px 14px; }
.ops-gauge { display:grid; grid-template-columns:78px minmax(0,1fr); grid-template-areas:"ring label" "ring note"; align-items:center; gap:2px 10px; text-align:left; }
.ops-gauge-ring { grid-area:ring; width:78px; height:78px; margin:0; }
.ops-gauge-ring::before { inset:7px; }
.ops-gauge-ring>div { width:58px; }
.ops-gauge-ring strong { font-size:16px; }
.ops-gauge-label { grid-area:label; align-self:end; margin:0; text-align:left; font-size:9.5px; white-space:nowrap; }
.ops-gauge-note { grid-area:note; align-self:start; margin:0; max-width:16ch; font-size:10.5px; line-height:1.4; }
.ops-forecast { padding:17px 19px; }
.ops-forecast h3 { margin:5px 0; font-size:15px; }
.ops-forecast>div>p:last-child { font-size:11px; line-height:1.55; }
.forecast-meter { margin-top:12px; }
.ops-forecast .btn.full { margin-top:12px; padding:8px 12px; font-size:12px; }
.viewer-command-grid { gap:14px; margin-bottom:14px; }
.card-head { padding:15px 17px; }
.card-head h3 { font-size:15px; }
.fleet-list { padding:5px 14px 10px; }
.fleet-row { min-height:52px; }
@keyframes workspace-card-in { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }
@media(min-width:1021px) {
 .noc-metrics { grid-template-columns:repeat(6,minmax(0,1fr)); }
}
@media(min-width:1021px) and (max-width:1320px) {
 .app-layout { grid-template-columns:220px 1fr; }
 .sidebar { padding-left:14px; padding-right:14px; }
 .page-content { padding-left:22px; padding-right:22px; }
 .topbar { padding-left:22px; padding-right:22px; }
 .health-gauges { grid-template-columns:repeat(4,minmax(0,1fr)); }
 .ops-gauge { grid-template-columns:1fr; grid-template-areas:"label" "ring" "note"; justify-items:center; text-align:center; gap:6px; }
 .ops-gauge-label,.ops-gauge-note { text-align:center; }
 .ops-gauge-note { max-width:16ch; }
}
@media(max-width:1020px) {
 .noc-metrics { grid-template-columns:repeat(3,minmax(0,1fr)); }
 .health-gauges { grid-template-columns:repeat(4,minmax(0,1fr)); }
 .ops-gauge { grid-template-columns:1fr; grid-template-areas:"label" "ring" "note"; justify-items:center; text-align:center; }
 .ops-gauge-label,.ops-gauge-note { text-align:center; }
 .ops-gauge-note { max-width:16ch; }
}
@media(max-width:700px) {
 .page-content { padding-top:16px; }
 .noc-metrics { grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; }
 .noc-metrics .metric { min-height:84px; padding:12px; }
 .health-gauges { grid-template-columns:repeat(2,minmax(0,1fr)); }
 .ops-gauge-ring { width:74px; height:74px; }
}

/* Shared product surfaces: Site directory, History, Reports and Guide. */
.page-heading:not(.noc-heading) {
 align-items:center;
 margin-bottom:16px;
 padding-bottom:16px;
 border-bottom:1px solid var(--stroke);
}
.page-heading:not(.noc-heading) h2 {
 margin:3px 0 4px;
 font-size:clamp(25px,2.3vw,32px);
 line-height:1.18;
 letter-spacing:-.045em;
}
.page-heading:not(.noc-heading) p:last-child { font-size:13px; line-height:1.6; }
/* Flex, not grid: a grid track (even repeat(auto-fit,minmax(...))) sizes
   every item the same way, including the "แสดงผล" button -- which forced
   it to claim a full 145px-minimum track just like every dropdown, even
   though its own content is under 100px wide. When the row ran out of
   room for one more 145px track, the WHOLE button wrapped to its own
   line even with visible slack remaining after the last date field
   (2026-09-09: "ทำไมต้องตกลงมา"). Flex lets every field flex/wrap on its
   own 145px basis while the button (no flex-basis given) just sizes to
   its own content and only wraps when there's truly no room left for it
   specifically. This also matches app.css's original .filters, which
   already got this right before this file's later display:grid silently
   overrode it back in an earlier density pass. */
.filters {
 display:flex;
 flex-wrap:wrap;
 gap:10px;
 align-items:end;
 margin-bottom:12px;
 padding:13px;
 border-radius:11px;
}
.filters label { flex:1 1 145px; min-width:0; gap:6px; color:var(--ink-secondary); font-size:10.5px; font-weight:600; }
.filters label:first-child:has(input[type="text"]),.filters label:first-child:has(input:not([type])) { flex-basis:300px; }
.filters :is(input,select) { min-height:40px; padding:9px 11px!important; }
.filters .btn { flex:none; min-height:40px; justify-content:center; padding:9px 14px; }
.date-presets { gap:6px; margin:0 0 14px; }
.preset-btn { min-height:31px; padding:5px 11px; border-radius:7px; font-size:11px; }
.preset-btn:hover { transform:translateY(-1px); }
.site-grid { grid-template-columns:repeat(auto-fill,minmax(245px,1fr)); gap:12px; }
.site-card.compact {
 position:relative;
 gap:8px;
 min-height:218px;
 padding:15px;
 border-radius:11px;
 overflow:hidden;
 transition:transform .18s ease,border-color .18s ease,box-shadow .18s ease;
}
.site-card.compact::before {
 content:"";
 position:absolute;
 inset:0 auto 0 0;
 width:3px;
 background:linear-gradient(180deg,var(--icon-tone,var(--accent)),color-mix(in srgb,var(--icon-tone,var(--accent)) 55%,#22c9d6 45%));
 opacity:.75;
}
.site-card.compact:hover { transform:translateY(-2px); border-color:color-mix(in srgb,var(--accent) 38%,var(--stroke))!important; }
.site-card.compact h3 { font-size:14px; line-height:1.45; }
.site-card.compact>p { min-height:1.45em; color:var(--ink-secondary); font-size:11px; line-height:1.45; }
.site-card.compact .site-card-head { margin-bottom:2px; }
.site-card.compact .solution-icon.small { width:32px; height:32px; border-radius:8px; }
.site-card.compact .site-solutions { min-height:24px; align-items:center; }
.site-card.compact .system-pill { padding:3px 8px; font-size:10px; }
.site-card.compact .site-compact-summary { padding:8px 0; }
.site-card.compact .site-issue { min-height:0; padding:7px 9px; border-radius:7px; }
.site-card.compact .site-issue p { font-size:10.5px; line-height:1.4; }
.site-card.compact .btn.full { min-height:36px; padding:8px 11px; font-size:11.5px; }
.activity-row { min-height:68px; padding:10px 15px; gap:12px; }
.activity-row:hover { background:var(--surface-soft)!important; }
.activity-site strong,.activity-job strong { font-size:13px; line-height:1.4; }
.activity-site small,.activity-meta,.activity-reason { font-size:10.5px; }
.activity-row>.link-btn { min-height:30px; padding:5px 8px; border:1px solid var(--stroke); border-radius:6px; text-decoration:none!important; }
.table-pager { padding:11px 14px; background:var(--surface-soft); }
.table-pager button { min-height:32px; border-radius:6px; }
.report-builder { padding:0; overflow:hidden; }
.report-options {
 grid-template-columns:repeat(5,minmax(125px,1fr)) auto auto;
 gap:10px;
 padding:16px;
 background:var(--surface-soft);
 border-bottom:1px solid var(--stroke);
}
.report-options label { gap:6px; color:var(--ink-secondary); font-size:10.5px; font-weight:600; }
.report-options :is(input,select) { min-height:40px; padding:9px 10px!important; }
.report-options .btn { min-height:40px; justify-content:center; padding:9px 12px; white-space:nowrap; }
.report-builder>.date-presets { margin:0; padding:12px 16px; border-bottom:1px solid var(--stroke); }
.report-summary { margin:0; padding:12px 16px; border-bottom:1px solid var(--stroke); }
.report-summary:empty { display:none; }
.report-summary strong { font-size:20px; }
.guide-layout { gap:14px; }
.guide-side { border-radius:11px; box-shadow:none!important; }
.guide-paper { border-radius:12px; box-shadow:none!important; }
.guide-hero { padding-top:34px; padding-bottom:30px; }
.guide-quick a { transition:transform .18s ease,border-color .18s ease,background .18s ease; }
.guide-quick a:hover { transform:translateY(-2px); border-color:color-mix(in srgb,var(--accent) 38%,var(--stroke)); }
.guide-section { padding-top:27px; padding-bottom:27px; }
:root[data-theme="light"] .site-card.compact:hover { box-shadow:0 10px 26px #17203312!important; }
:root[data-theme="light"] .activity-row>.link-btn { color:#4338ca; background:#f7f7ff; }
:root[data-theme="light"] .report-options { background:#f0f3f7; }
@media(prefers-reduced-motion:no-preference) {
 .site-card.compact { animation:workspace-card-in .38s cubic-bezier(.2,.8,.2,1) both; }
 .site-card.compact:nth-child(2n) { animation-delay:35ms; }
 .site-card.compact:nth-child(3n) { animation-delay:70ms; }
}
@media(max-width:1180px) {
 .report-options { grid-template-columns:repeat(3,minmax(0,1fr)); }
 .report-options .btn { width:100%; }
}
@media(max-width:760px) {
 .page-heading:not(.noc-heading) { align-items:flex-start; }
 .filters label { flex-basis:calc(50% - 5px); }
 .filters label:first-child:has(input[type="text"]),.filters label:first-child:has(input:not([type])) { flex-basis:100%; }
 .filters .btn { flex-basis:100%; width:100%; }
 .report-options { grid-template-columns:repeat(2,minmax(0,1fr)); }
 .report-options .btn { grid-column:span 1; }
 .guide-hero { padding-top:26px; }
}
@media(max-width:520px) {
 .filters label { flex-basis:100%; }
 .report-options { grid-template-columns:1fr; }
 .report-options .btn { grid-column:1; }
 .site-grid { grid-template-columns:1fr; }
}
@media(min-width:1101px) {
 #jobsView th:nth-child(1) { width:28%; } #jobsView th:nth-child(2) { width:19%; } #jobsView th:nth-child(3) { width:12%; } #jobsView th:nth-child(4) { width:25%; } #jobsView th:nth-child(5) { width:10%; } #jobsView th:nth-child(6) { width:6%; }
 /* 6 columns since the detail column was dropped (the drawer shows the full message). This file loads after admin-pro.css, so these are the widths that actually apply. */
 #incidentsView th:nth-child(1) { width:9%; } #incidentsView th:nth-child(2) { width:23%; } #incidentsView th:nth-child(3) { width:28%; } #incidentsView th:nth-child(4) { width:11%; } #incidentsView th:nth-child(5) { width:11%; } #incidentsView th:nth-child(6) { width:18%; }
}
/* Geometry describes the actual solution connections; motion is decorative, not a live packet counter. */
.solution-map-canvas { height:380px; min-height:380px; }
.map-connections { position:absolute; inset:0; width:100%; height:100%; pointer-events:none; overflow:visible; }
.map-connection { fill:none; stroke:#38bdf83d; stroke-width:.3; }
.map-data-flow { fill:none; stroke:#67e8f9; stroke-width:.6; stroke-linecap:round; stroke-dasharray:4 96; filter:drop-shadow(0 0 3px #38bdf8); animation:map-transfer 3.4s linear infinite; }
.map-orbit { width:240px; height:240px; background:conic-gradient(from 0deg,transparent 65%,#22d3ee12 90%,#22d3ee40); animation:map-sweep 18s linear infinite; pointer-events:none; }
.map-orbit::before { width:6px; height:6px; left:50%; top:-3px; border-radius:50%; background:#67e8f9; box-shadow:0 0 6px #22d3ee; }
.map-orbit::after { display:none; }
.map-core { position:absolute; left:50%; top:48%; transform:translate(-50%,-50%); animation:map-core-glow 4s ease-in-out infinite; }
.solution-map-node { width:min(174px,43%); min-height:76px; bottom:auto!important; right:auto!important; transform:translate(-50%,-50%)!important; grid-template-columns:26px minmax(0,1fr); padding:10px; gap:3px 8px; animation:map-node-glow 4s ease-in-out infinite; animation-delay:var(--node-delay,0s); }
.solution-map-node strong { white-space:normal; overflow:visible; text-overflow:clip; font-size:12px; line-height:1.4; }
.solution-map-node small { font-size:11px; }
.solution-map-node>span { width:26px; height:30px; }
:root[data-theme="light"] .map-data-flow { stroke:#0788ac; filter:none; }
:root[data-theme="light"] .map-connection { stroke:#1687ab55; }
@keyframes map-transfer { to { stroke-dashoffset:-100; } }
@keyframes map-sweep { to { transform:rotate(360deg); } }
@keyframes map-core-glow { 50% { box-shadow:0 0 14px #0ea5e922; border-color:#67e8f9; } }
@keyframes map-node-glow { 50% { border-color:var(--node-tone); box-shadow:0 0 8px color-mix(in srgb,var(--node-tone) 10%,transparent); } }
@media(max-width:430px) { .solution-map-node { grid-template-columns:1fr; text-align:center; padding:9px 5px; } .solution-map-node>span { display:none; } .solution-map-node strong { font-size:11px; } .solution-map-node small { font-size:10px; } .map-core { width:82px; height:82px; } }
:root[data-motion="paused"] *, :root[data-motion="paused"] *::before, :root[data-motion="paused"] *::after { animation:none!important; transition:none!important; }
@media(prefers-reduced-motion:reduce) { *,*::before,*::after { animation:none!important; scroll-behavior:auto!important; transition:none!important; } }

/* Bug-review pass: source-accurate latest sessions without the long card wall. */
.topbar-heading { display:flex; align-items:center; gap:11px; min-width:0; margin-right:auto; }
.topbar-title-icon {
 display:grid; place-items:center; flex:0 0 auto; width:34px; height:34px;
 border:1px solid color-mix(in srgb,var(--accent) 36%,var(--stroke)); border-radius:9px;
 color:var(--accent); background:linear-gradient(145deg,var(--accent-soft),transparent);
 box-shadow:inset 0 1px color-mix(in srgb,#fff 16%,transparent),0 7px 20px color-mix(in srgb,var(--accent) 10%,transparent);
 font:700 15px/1 var(--font-mono);
}
.topbar-heading h1 { font-size:17px; letter-spacing:-.025em; }
.topbar-heading p { margin-top:3px; }
.company-label { padding:14px 18px 8px!important; color:var(--ink-secondary)!important; font-size:11px!important; letter-spacing:.075em!important; }
.site-id strong { color:var(--ink); font-size:17px!important; line-height:1.35; letter-spacing:-.015em; }
.site-id span { display:block; margin-top:4px; }
.site-card.compact h3 { min-height:2.8em; color:var(--ink); font-size:15px; line-height:1.4; white-space:normal; overflow:visible; text-overflow:clip; }

.veeam-session-table-head,.compact-session>summary {
 display:grid; grid-template-columns:minmax(260px,1.65fr) 92px minmax(150px,.9fr) minmax(150px,.9fr) 92px 24px;
 /* start:  job name carries a two-line label+subtitle while the status pill
    is a single short line -- centering each column on the tallest one made
    every column's text begin at a different height down the row. Top-align
    everything instead, then re-center just the small single-line elements
    (pill, chevron) on their own. */
 align-items:start; gap:12px;
}
.compact-session>summary>.pill,.compact-session>summary .session-chevron { align-self:center; }
.veeam-session-table-head { padding:10px 14px; border-bottom:1px solid var(--stroke); color:var(--ink-secondary); background:var(--surface-soft); font-size:11px; }
.veeam-session-list { gap:0; padding-top:0; }
.veeam-session.compact-session { border-width:0 0 1px 3px; border-radius:0; background:transparent!important; box-shadow:none; }
.veeam-session.compact-session:last-child { border-bottom:0; }
.compact-session>summary { min-height:68px; padding:10px 14px; list-style:none; cursor:pointer; transition:background .18s ease; }
.compact-session>summary::-webkit-details-marker { display:none; }
.compact-session>summary:hover,.compact-session[open]>summary { background:var(--surface-soft); }
.session-job { display:flex; align-items:center; gap:10px; min-width:0; }
.session-job>span:last-child { min-width:0; }
.session-job strong,.session-job small,.compact-session time small,.compact-session time strong,.session-size small,.session-size strong { display:block; }
.session-job strong { color:var(--ink); font-size:13px; line-height:1.35; overflow-wrap:anywhere; }
.session-job small,.compact-session time small,.session-size small { margin-top:3px; color:var(--ink-secondary); font-size:10px; }
/* The subtitle line grew a "· <destination>" suffix (2026-09-09) which can
   run long for a repository path like "QNAP iSCSI Storage / QNas-Backup
   (E:\Backup)". Single-line ellipsis was tried first, but that HIDES real
   detail behind a hover-only tooltip -- the user explicitly wants it kept
   visible even if that means wrapping to another line (2026-09-09: "ไปเริ่ม
   บรรทัดใหม่ก็ได้ไม่ใช่ตัดข้อความจนไม่เห็นรายละเอียด" -- wrapping to a new
   line is fine, just don't cut the text so detail disappears). The grid row
   (.compact-session>summary, align-items:start) already sizes to its
   tallest cell, so a taller subtitle here just makes that one row taller. */
.session-job small { overflow-wrap:anywhere; white-space:normal; }
/* 2026-10-19 ("ทำไมมันยาวเกิน 1 บรรทัด" -- "Nightly VM Backup - VTG-NODE01 / vtg-backup" broke at "vtg-"): the name and
   the line under it stay on one line and app.js (fitSessionText) shrinks a long one until it fits -- still never cut;
   only a line too long even at its smallest wraps again (.is-wrap), as the 2026-09-09 rule above wants */
.session-job strong,.session-job small { white-space:nowrap; overflow-wrap:normal; }
.session-job strong.is-wrap,.session-job small.is-wrap { white-space:normal; overflow-wrap:break-word; }
.compact-session time strong,.session-size strong { margin-top:4px; color:var(--ink); font:600 11px/1.35 var(--font-mono); }
.session-chevron { color:var(--accent); font-size:20px; transition:transform .2s ease; }
.compact-session[open] .session-chevron { transform:rotate(180deg); }
.compact-session-detail { border-top:1px solid var(--stroke); background:color-mix(in srgb,var(--surface-soft) 62%,transparent); }
.compact-session-detail .session-fact { background:var(--surface); }
.compact-session-detail .session-issue { margin-top:12px; }
.compact-session-detail .protected-list { background:var(--surface); }

@media(prefers-reduced-motion:no-preference) {
 .topbar-title-icon { animation:header-icon-breathe 3.6s ease-in-out infinite; }
 .site-row[open] .site-row-detail { animation:workspace-detail-in .28s cubic-bezier(.2,.8,.2,1) both; }
 .compact-session { animation:workspace-row-in .3s cubic-bezier(.2,.8,.2,1) both; }
 .compact-session:nth-child(2) { animation-delay:35ms; }
 .compact-session:nth-child(3) { animation-delay:70ms; }
 .compact-session:nth-child(4) { animation-delay:105ms; }
}
@keyframes header-icon-breathe { 50% { border-color:var(--accent); box-shadow:0 0 22px color-mix(in srgb,var(--accent) 20%,transparent); } }
@keyframes workspace-detail-in { from { opacity:.25; transform:translateY(-5px); } to { opacity:1; transform:none; } }
@keyframes workspace-row-in { from { opacity:0; transform:translateX(-6px); } to { opacity:1; transform:none; } }

@media(max-width:980px) {
 .veeam-session-table-head { display:none; }
 .compact-session>summary { grid-template-columns:minmax(0,1fr) auto 24px; gap:10px; }
 .compact-session>summary time,.compact-session>summary .session-size { grid-row:2; }
 .compact-session>summary time:nth-of-type(1) { grid-column:1; }
 .compact-session>summary time:nth-of-type(2) { grid-column:2; }
 .compact-session>summary .session-size { grid-column:1; grid-row:3; }
 .compact-session>summary .session-chevron { grid-column:3; grid-row:1; }
 .compact-session>summary>.pill { grid-column:2; grid-row:1; }
}
@media(max-width:620px) {
 .topbar-title-icon { width:31px; height:31px; }
 .topbar-heading p { display:none; }
 .compact-session>summary { grid-template-columns:minmax(0,1fr) auto 22px; }
 .compact-session>summary time:nth-of-type(2) { grid-column:1; grid-row:3; }
 .compact-session>summary .session-size { grid-column:2; grid-row:2/4; align-self:center; }
}

/* Login hero composition: keep the copy centered and use the animated backup
   system to occupy the upper field instead of leaving a large empty region. */
@media(min-width:851px) {
 .auth-hero { position:relative; justify-content:center; align-items:center; }
 .auth-hero .hero-body {
   width:min(680px,100%);
   margin:auto;
   padding:250px 0 112px;
   text-align:center;
 }
 .auth-hero .live-chip { display:inline-flex; margin:0 auto 16px; }
 .auth-hero .hero-tag { justify-content:center; margin:0 auto 18px; }
 .auth-hero h1 {
   margin:0 auto 20px;
   font-size:clamp(36px,4vw,56px);
   line-height:1.15;
   letter-spacing:-.035em;
 }
 .auth-hero .hero-body>p:last-child {
   max-width:560px;
   margin:0 auto;
   font-size:15px;
 }
 .auth-hero .backup-animation {
   left:50%;
   right:auto;
   top:92px;
   bottom:auto;
   width:380px;
   height:380px;
   opacity:.68;
   transform:translateX(-50%) scale(.78);
   transform-origin:center;
 }
 .auth-hero .hero-proof { bottom:24px; }
}

/* 2026-09-07: switched from position:sticky to position:fixed. Two earlier
   fixes each found and removed a real display:flex rule that reproducibly
   blanked the sidebar (admin.css's base rule, then the same mistake
   independently in admin-pro.css's @media(min-width:1101px) block), both
   confirmed live via curl -- yet after ALSO adding a !important
   display/visibility/opacity/position:sticky guard here, the user still
   reported it going blank on scroll. That specifically rules out
   display/visibility/opacity as the cause (this guard already forced
   those) and points at position:sticky itself: sticky positions relative
   to the nearest ancestor with an actual scroll mechanism, and if
   something in this page's ancestor chain gives it a DIFFERENT scrolling
   context than the one the user visually scrolls (two nested scrollers,
   or one that behaves unexpectedly), the sidebar can stick relative to a
   frame that never moves -- from the visible viewport it looks like it
   scrolled away and vanished, which reads exactly like "still empty
   after scrolling down". position:fixed has no such ambiguity: it is
   always relative to the viewport (unless an ancestor has
   transform/filter/perspective/will-change, none of which any ancestor
   here sets), so it cannot mis-stick to the wrong scroll frame.
   IMPORTANT CORRECTION: a position:fixed grid item is removed from the
   grid's auto-placement entirely (not just visually) -- .admin-main then
   becomes the first in-flow child and gets auto-placed into column 1
   itself, landing underneath/behind the fixed sidebar instead of beside
   it. That first attempt at this fix shipped without noticing that and
   made the whole admin content area appear blank (2026-09-07 report).
   SECOND CORRECTION, same day: a margin-left matching the sidebar width
   was not enough either -- .admin-main was still auto-placed into grid
   column 1 (the sidebar's own 232px-wide track), so it kept column 1's
   narrow WIDTH and margin-left just shifted that already-too-narrow box
   further right, leaving column 2's actual space empty (reported as the
   content squeezed into a thin strip with a huge blank area beside it).
   margin-left only fixes position, not width. The correct fix is to
   force .admin-main into grid column 2 explicitly, so it gets that
   track's own minmax(0,1fr) sizing regardless of what column 1 does or
   doesn't contain. */
.admin-sidebar {
  display: block !important;
  visibility: visible !important;
  opacity: 1 !important;
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  width: 232px !important;
  height: 100vh !important;
  overflow-y: auto !important;
  z-index: 5 !important;
}
.admin-main {
  grid-column: 2 !important;
  margin-left: 0 !important;
  /* width:auto measured 1239px in a 1670px-wide grid track (confirmed with
     a real headless-Chrome layout probe, 2026-09-08) -- despite
     justify-self computing to "stretch", this grid item was shrink-wrapping
     to its content's needed width instead of filling the track. An
     explicit width:100% (not auto) measured the full 1670px in the same
     probe, so use that instead of relying on stretch alignment. */
  width: 100% !important;
  /* admin-pro.css has its own later, non-!important max-width:100% (an
     overflow-safety rule for narrow screens) that was silently winning over
     every attempt to widen this element on wide screens -- !important here
     is the only way to guarantee this actually wins (2026-09-08: "ยังไม่เต็ม
     หน้าเลยหน้านี้", reported again after two prior non-!important widening
     attempts). 100% resolves against the grid track's own width (already
     unconstrained via minmax(0,1fr)), so this really does let it fill the
     viewport on any screen size instead of guessing another fixed number. */
  max-width: 100% !important;
}
@media(max-width:1180px) {
  .admin-sidebar { width: 220px !important; }
}
@media(max-width:900px) {
  .admin-main { grid-column: 1 !important; }
}
.admin-sidebar nav {
  display: grid !important;
  visibility: visible !important;
  opacity: 1 !important;
  height: auto !important;
}
.admin-sidebar .admin-nav {
  display: flex !important;
  visibility: visible !important;
  opacity: 1 !important;
}
.admin-sidebar .sidebar-bottom,
.admin-sidebar .sidebar-bottom * {
  visibility: visible !important;
  opacity: 1 !important;
}
@media(max-width:900px) {
  .admin-sidebar { position: sticky !important; height: auto !important; }
}

/* When the shared shell becomes one column, the desktop-height sidebar must
   become a compact navigation header, not an entire empty viewport. */
@media(max-width:1000px) {
  .sidebar { position:static; height:auto; min-height:0; padding:14px 16px 10px; gap:10px; border-right:0; border-bottom:1px solid var(--stroke); }
  .sidebar .brand { justify-content:flex-start; margin:0; }
  .sidebar .brand > span { display:block; }
  .sidebar .brand > .brand-mark { display:grid; width:32px; height:32px; flex-basis:32px; }
  .sidebar .module-switch { grid-template-columns:repeat(2,minmax(0,1fr)); margin:0; }
  .sidebar .module-switch a { flex-direction:row; justify-content:center; min-width:0; }
  .sidebar .module-switch a span { display:block; overflow:hidden; text-overflow:ellipsis; }
  .sidebar nav { display:flex; gap:5px; min-width:0; width:100%; overflow-x:auto; padding-bottom:3px; }
  .sidebar .nav-item { flex:0 0 auto; min-height:38px; padding:7px 10px; gap:7px; }
  .sidebar .nav-item span { display:inline; }
  .sidebar .nav-label { display:none; }
}
@media(max-width:760px) {
  /* The older generic topbar > div rule also matched this moved footer and
     placed it on top of the page title. Give it its own full-width row. */
  .topbar > div.sidebar-foot.mobile-account-controls { grid-column:1/-1; grid-row:3; }
}
