/* Open Props — design-token foundation (colours, shadows, easing, scales). Our semantic tokens below are backed by its ramps, so the rest of the CSS (which references var(--accent) etc.) is untouched. */ @import "open-props/style"; :root { /* appearance (overridden at runtime by appearance.ts) */ --row-h: 30px; --bar-h: 18px; --bar-font: 11px; --label-font: 12px; --label-w: 340px; /* ---- design tokens (light), backed by Open Props ---- */ --bg: #ffffff; --surface: var(--gray-0); --surface-2: var(--gray-1); --border: var(--gray-3); --border-strong: var(--gray-4); --text: var(--gray-9); --text-muted: var(--gray-6); --font-sans: "IBM Plex Sans", -apple-system, "Segoe UI", Roboto, Arial, sans-serif; --accent: #4f46e5; --accent-weak: rgba(79, 70, 229, .12); --accent-ring: rgba(79, 70, 229, .22); --radius: 8px; --radius-sm: 6px; --shadow-sm: var(--shadow-1); --shadow-md: var(--shadow-3); --transition: .13s var(--ease-3); /* timeline / map surfaces (built on the tokens above) */ --grid-line: var(--border); --row-even: var(--gray-1); --row-odd: #ffffff; --row-hover: #fff3cd; --month-hover: rgba(79, 70, 229, .08); --tip-bg: var(--gray-9); --tip-text: #ffffff; --tip-sub: var(--gray-4); --today: #ef5350; } /* Dark theme — single source of truth is data-theme on , set by the no-flash inline script in index.html (defaults to prefers-color-scheme). */ :root[data-theme="dark"] { --bg: #0f1420; --surface: #161c2b; --surface-2: #1e2637; --border: #273043; --border-strong: #33405a; --text: #e6e9ef; --text-muted: #93a0b5; --accent: #5b8def; --accent-weak: rgba(91, 141, 239, .16); --accent-ring: rgba(91, 141, 239, .30); --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4); --shadow-md: 0 6px 18px rgba(0, 0, 0, .5); --row-even: #141a27; --row-odd: #0f1420; --row-hover: #33361f; --month-hover: rgba(91, 141, 239, .12); --tip-bg: #0b0f18; } * { box-sizing: border-box; } html, body { height: 100%; margin: 0; overflow: hidden; } body { display: flex; flex-direction: column; font-family: var(--font-sans); background: var(--bg); color: var(--text); } header { flex: 0 0 auto; padding: 12px 18px; border-bottom: 1px solid var(--border); box-shadow: var(--shadow-sm); display: flex; gap: 18px; align-items: stretch; /* Responsive: the fields group compresses (and wraps its own fields) first; if the window is still too narrow, whole blocks drop to the next row instead of overlapping. */ flex-wrap: wrap; align-content: flex-start; background: var(--bg); /* position:relative makes the z-index actually take effect, so the header (and its open dropdown panels) forms a stacking context above the timeline — otherwise the column-resizer line bleeds over the filter dropdown lists. */ position: relative; z-index: 40; } /* Header groups. Flat now (no boxes) — the header itself is the panel. */ .hgroup { display: flex; align-items: center; gap: var(--size-3); padding: var(--size-1) 0; flex-shrink: 1; min-width: 0; } /* The fields group is the one that gives way first when space runs out. */ .hgroup-fields { flex-shrink: 4; min-width: 0; display: grid; grid-template-columns: repeat(4, 170px); gap: 12px 14px; align-items: start; align-content: start; } /* Compact grid: 4 dropdowns on row 1; the two dates + search fall to row 2. */ .hgroup-fields .field { min-width: 0; } .hgroup-fields .dropdown, .hgroup-fields .dropdown-btn, .hgroup-fields input[type=text], .hgroup-fields input[type=date] { min-width: 0; width: 100%; } @media (max-width: 760px) { .hgroup-fields { grid-template-columns: repeat(2, minmax(120px, 1fr)); } } /* Fields group: top-align so the date input sits UNDER Город/Бренд. */ .hgroup-fields { align-items: flex-start; } /* ---- date-range field + calendar popup ---- */ .field-dates { grid-column: span 2; } .field-dates .dr-field { max-width: 333px; } /* the "Период" field is 40px narrower than its 2-col slot */ .dr-native { display: none; } .daterange { position: relative; } .dr-field { display: flex; align-items: center; gap: 8px; width: 100%; box-sizing: border-box; height: 36px; padding: 0 10px; cursor: pointer; font-size: 13px; color: var(--text-muted); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg); transition: border-color var(--transition); } .dr-field:hover { border-color: var(--border-strong); } .dr-field.has-value { color: var(--text); } .dr-ico { width: 16px; height: 16px; flex: 0 0 auto; color: var(--accent); } .dr-text { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; } .dr-clear { border: none; background: none; color: var(--text-muted); cursor: pointer; font-size: 16px; line-height: 1; padding: 0 2px; flex: 0 0 auto; } .dr-clear:hover { color: var(--text); } .dr-cal { position: absolute; top: calc(100% + 4px); left: 0; z-index: 40; width: 252px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-md); padding: 10px; font-variant-numeric: tabular-nums; } .dr-cal[hidden] { display: none; } .dr-cal-h { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; } .dr-cal-title { font-size: 13px; font-weight: 600; color: var(--text); } .dr-nav { border: none; background: none; color: var(--text-muted); cursor: pointer; font-size: 18px; line-height: 1; width: 26px; height: 26px; border-radius: var(--radius-sm); } .dr-nav:hover { background: var(--surface); color: var(--text); } .dr-grid { display: grid; grid-template-columns: repeat(7, 1fr); } .dr-wd { text-align: center; font-size: 11px; color: var(--text-muted); padding-bottom: 4px; } .dr-day { position: relative; border: none; background: none; padding: 2px 0; cursor: pointer; display: flex; align-items: center; justify-content: center; height: 30px; } .dr-day::before { content: ""; position: absolute; inset: 0; z-index: 0; } .dr-day.rng::before { background: #eef0fe; } .dr-day.s::before { background: linear-gradient(to right, transparent 50%, #eef0fe 50%); } .dr-day.e::before { background: linear-gradient(to left, transparent 50%, #eef0fe 50%); } .dr-day.s.e::before { background: transparent; } .dr-num { position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 50%; font-size: 12px; color: var(--text); } .dr-day:hover .dr-num { background: var(--surface-2); } .dr-day.s .dr-num, .dr-day.e .dr-num { background: var(--accent); color: #fff; font-weight: 600; } .dr-day.s:hover .dr-num, .dr-day.e:hover .dr-num { background: var(--accent); } .dr-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); } .dr-reset { border: none; background: none; color: var(--text-muted); cursor: pointer; font-size: 13px; padding: 7px 10px; border-radius: var(--radius-sm); } .dr-reset:hover { background: var(--surface); color: var(--text); } .dr-apply { border: none; background: var(--accent); color: #fff; cursor: pointer; font-size: 13px; font-weight: 600; padding: 7px 16px; border-radius: var(--radius-sm); transition: background var(--transition); } .dr-apply:hover { background: var(--accent-strong, #4338ca); } .dr-apply:disabled { opacity: .45; cursor: default; } .fcol { display: flex; flex-direction: column; gap: 8px; } input[type=date], input[type=text] { height: 36px; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0 10px; font-size: 13px; min-width: 0; width: 100%; background: var(--bg); color: var(--text); transition: border-color var(--transition), box-shadow var(--transition); } input[type=date]:hover, input[type=text]:hover { border-color: var(--border-strong); } input[type=date]:focus, input[type=text]:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); } input::placeholder { color: var(--text-muted); } /* Search field: magnifier icon inside the input. */ #search { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa4b2' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: 10px center; background-size: 15px; padding-left: 32px; } :root[data-theme="dark"] input[type=date]::-webkit-calendar-picker-indicator { filter: invert(1) opacity(.65); } /* Compact controls block: scale (label + short slider + round Оформление) on top, the three checkboxes stacked below. */ .hgroup-controls { flex-direction: column; align-items: flex-start; gap: 8px; } .zoom-row { display: flex; align-items: center; gap: 8px; } /* Toggles: aligned to the filter *controls* (not the labels) — Бренд + Компания share the top row, then Коллизии and Все поверхности, evenly distributed between the top of the first control box and the bottom of Поиск. */ .checks { display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; flex: 1; align-self: stretch; padding: 19px 0 0; } .checks .checkbox-field { align-self: flex-start; } .checks-row { display: flex; flex-direction: row; align-items: center; gap: 18px; } /* Let the brand block fill the header height so the counters can sit at the bottom, level with the date fields / mode switch. */ .hgroup-brand { align-items: stretch; } .brand { display: flex; flex-direction: column; justify-content: flex-start; line-height: 1.2; } .brand-name { font-size: 23px; font-weight: 700; white-space: nowrap; } .brand-sub { font-size: 15px; font-weight: 400; color: var(--text-muted); white-space: nowrap; } .field { display: flex; flex-direction: column; gap: var(--size-1); } .field label { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em; font-weight: 500; } /* Counters — compact inset inside the brand block. */ .brand #status { margin-top: auto; } /* Scale group: stack the "Оформление" button under the zoom slider. */ .checkbox-field { flex-direction: row; align-items: center; gap: 6px; align-self: center; } .checkbox-field label { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text); text-transform: none; letter-spacing: normal; font-weight: 400; cursor: pointer; white-space: nowrap; } /* Toggle switch: the checkbox keeps its semantics/JS, only the look changes. Scoped to .checkbox-field so the dropdown option checkboxes stay normal. */ .checkbox-field input[type=checkbox] { appearance: none; -webkit-appearance: none; margin: 0; flex: 0 0 auto; width: 34px; height: 20px; border-radius: 20px; background: #cbd0d8; position: relative; cursor: pointer; transition: background var(--transition); } .checkbox-field input[type=checkbox]::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .25); transition: left var(--transition); } .checkbox-field input[type=checkbox]:checked { background: var(--accent); } .checkbox-field input[type=checkbox]:checked::after { left: 16px; } .checkbox-field input[type=checkbox]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } .zoom-field { gap: 4px; } .zoom-field label { white-space: nowrap; } .zoom-field .zoom-row { position: relative; width: 120px; padding-bottom: 24px; display: block; } /* The scale control floats over the top-right of the timeline, just below the time axis (JS sets `top` = axis bottom + 5px; this is only a fallback). */ #chart-wrap #zoom-field { position: absolute; top: 52px; right: 16px; z-index: 20; background: rgba(255, 255, 255, .92); border-radius: 8px; padding: 3px 12px 4px; box-shadow: var(--shadow-md); } .zoom-field input[type=range] { -webkit-appearance: none; appearance: none; width: 100%; height: 6px; margin: 0; border-radius: 4px; cursor: pointer; outline: none; background: linear-gradient(to right, var(--accent) var(--zoom-fill, 0%), var(--border-strong) var(--zoom-fill, 0%)); } .zoom-field input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 2px solid var(--accent); box-shadow: 0 1px 3px rgba(0, 0, 0, .3); cursor: pointer; } .zoom-field input[type=range]::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 2px solid var(--accent); box-shadow: 0 1px 3px rgba(0, 0, 0, .3); cursor: pointer; } .zoom-field input[type=range]:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; } /* Value bubble that rides below the slider thumb, pointing up (JS sets `left`). */ .zoom-bubble { position: absolute; bottom: 0; top: auto; left: 0; transform: translateX(-50%); background: var(--accent); color: #fff; font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 6px; white-space: nowrap; pointer-events: none; font-variant-numeric: tabular-nums; } .zoom-bubble::after { content: ""; position: absolute; top: -4px; bottom: auto; left: 50%; transform: translateX(-50%); border: 4px solid transparent; border-bottom-color: var(--accent); border-top: 0; } /* checkbox dropdown filter */ .dropdown { position: relative; } .dropdown-btn { height: 36px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg); color: var(--text); padding: 0 12px; font-size: 13px; min-width: 180px; text-align: left; cursor: pointer; display: flex; justify-content: space-between; align-items: center; gap: 8px; transition: border-color var(--transition), box-shadow var(--transition); } .dropdown-btn:hover { border-color: var(--border-strong); } .dropdown.open .dropdown-btn { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); } .dropdown-btn .caret { font-size: 10px; color: var(--text-muted); } .dropdown-panel { display: none; position: absolute; top: calc(100% + 4px); left: 0; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-md); padding: 6px 0; min-width: 220px; max-height: 280px; overflow-y: auto; z-index: 30; } .dropdown.open .dropdown-panel { display: block; } .dropdown-panel label { display: flex; align-items: center; gap: var(--size-2); padding: var(--size-2) var(--size-3); font-size: 13px; cursor: pointer; white-space: nowrap; color: var(--text); /* Option labels are