{% extends "base.html" %} {% block title %}Factcat — Events{% endblock %} {% block extra_head %} {% endblock %} {% block extra_css %} main.workspace { display: block; flex: 1; min-height: 0; } form.workspace-form { display: grid; grid-template-columns: var(--fc-config-col, 22rem) 0 minmax(0, 1fr); height: 100%; min-height: 0; } form.workspace-form.config-collapsed { grid-template-columns: 0 0 minmax(0, 1fr); } form.workspace-form.config-collapsed .filters { display: none; } .filters { background: var(--fc-snow); padding: 1.25rem; border-right: 1px solid var(--fc-line); overflow-y: auto; min-height: 0; grid-column: 1; grid-row: 1; } .col-divider { grid-column: 2; grid-row: 1; } .results { grid-column: 3; grid-row: 1; } .col-divider { cursor: col-resize; position: relative; width: 9px; margin-left: -5px; z-index: 25; display: flex; align-items: center; justify-content: center; touch-action: none; min-height: 0; } .col-divider::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; transform: translateX(-50%); background: var(--fc-ochre); opacity: 0; } .col-divider:hover::before, .col-divider.dragging::before { opacity: 1; } form.workspace-form.config-collapsed .col-divider { cursor: default; width: 1.5rem; margin-left: 0; justify-content: flex-start; } form.workspace-form.config-collapsed .col-divider::before { display: none; } form.workspace-form.config-collapsed .col-toggle { width: 1.35rem; height: 3.5rem; border-left: 0; border-radius: 0 0.5rem 0.5rem 0; color: var(--fc-ink); border-color: var(--fc-slate); box-shadow: 0 1px 4px color-mix(in srgb, var(--fc-ink) 22%, transparent); } .col-flyout { position: absolute; left: calc(100% + 0.3rem); top: 50%; transform: translateY(-50%); display: flex; flex-direction: column; gap: 0.2rem; padding: 0.25rem; background: var(--fc-snow); border: 1px solid var(--fc-line); border-radius: 0.4rem; box-shadow: 0 0.35rem 1rem color-mix(in srgb, var(--fc-ink) 18%, transparent); opacity: 0; pointer-events: none; transition: opacity 0.12s ease 0.18s; z-index: 30; } .col-divider:hover .col-flyout, .col-flyout:hover { opacity: 1; pointer-events: auto; } .col-divider.dragging .col-flyout { opacity: 0; pointer-events: none; } .col-flyout button { margin: 0; padding: 0.3rem; width: 1.7rem; height: 1.7rem; display: inline-flex; align-items: center; justify-content: center; background: var(--fc-snow); color: var(--fc-slate); border: 0; border-radius: 0.3rem; cursor: pointer; } .col-flyout button:hover { background: var(--fc-paper); color: var(--fc-ink); } .col-flyout button svg { width: 0.9rem; height: 0.9rem; display: block; } .col-toggle { margin: 0; padding: 0; position: relative; z-index: 1; width: 1.05rem; height: 2.75rem; display: inline-flex; align-items: center; justify-content: center; background: var(--fc-snow); color: var(--fc-slate); border: 1px solid var(--fc-line); border-radius: 0.5rem; cursor: pointer; } .col-toggle:hover { color: var(--fc-ink); border-color: var(--fc-ochre); } .col-toggle svg { width: 0.7rem; height: 0.7rem; display: block; } .col-toggle .chev-right { display: none; } form.config-collapsed .col-toggle .chev-left { display: none; } form.config-collapsed .col-toggle .chev-right { display: block; } .results-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.45rem 0.85rem; padding: 0.2rem 0.35rem 0.45rem; } .results-toolbar .toolbar-field { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; } .results-toolbar .toolbar-field label { display: block; margin: 0; font-size: 0.7rem; font-weight: 600; color: var(--fc-slate); } .results-toolbar select, .results-toolbar input[type="number"], .results-toolbar input[type="date"] { width: auto; margin: 0; font-size: 0.8rem; } .results-toolbar #grain { min-width: 9.75rem; } .results-toolbar #range_choice { min-width: 11.5rem; } .results-toolbar .toolbar-extras { display: flex; flex-wrap: nowrap; align-items: center; gap: 0.55rem 0.75rem; flex: 1 1 auto; min-width: 0; overflow-x: auto; } .toolbar-cluster { display: flex; flex-wrap: nowrap; align-items: center; gap: 0.35rem; min-width: 0; } .toolbar-cluster label, .toolbar-cluster span { display: inline; margin: 0; font-size: 0.75rem; font-weight: 500; color: var(--fc-ink); white-space: nowrap; } .toolbar-cluster input[type="number"] { width: 4.25rem; } .toolbar-cluster input[type="date"] { width: 9.6rem; } .toolbar-cluster select { width: auto; } .toolbar-cluster input[type="checkbox"] { width: auto; margin: 0; } .results-toolbar #custom_kind { min-width: 8.25rem; } .results-toolbar #run-row { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0 auto; flex-wrap: wrap; } .results-toolbar #run-row button { margin: 0; } .results { display: block; padding: 0 0.5rem 0.5rem; min-height: 0; overflow-y: auto; background: var(--fc-paper); } .results-toolbar { position: sticky; top: 0; z-index: 20; background: var(--fc-paper); margin: 0 -0.5rem 0.5rem; padding: 0.55rem 0.5rem 0.45rem; border-bottom: 1px solid var(--fc-line); } .pane + .pane { margin-top: 0.5rem; } /* The divider's own height provides the chart-table gap; when a closed pane hides it, the next card supplies the same 0.5rem so every inter-card gap is identical in every collapse state. */ .row-divider[hidden] + .pane { margin-top: 0.5rem; } .row-divider { height: 0.5rem; cursor: row-resize; touch-action: none; position: relative; } .row-divider::after { content: ""; position: absolute; left: 50%; top: 50%; width: 2.5rem; height: 3px; border-radius: 2px; transform: translate(-50%, -50%); background: var(--fc-ochre); opacity: 0; } .row-divider:hover::after, .row-divider.dragging::after { opacity: 1; } .row-divider[hidden] { display: none; } .pane-chart:not(.closed) { height: var(--fc-chart-px, 55vh); min-height: 12rem; } .pane-table:not(.closed) .pane-body { max-height: 75vh; } .pane.closed .pane-body { display: none; } .pane-toggle { margin: 0 0 0 0.25rem; padding: 0.15rem; width: 1.5rem; height: 1.5rem; display: inline-flex; align-items: center; justify-content: center; background: none; border: 0; border-radius: 0.25rem; color: var(--fc-slate); cursor: pointer; flex: 0 0 auto; } .pane-toggle:hover { color: var(--fc-ink); background: var(--fc-paper); } .pane-toggle svg { width: 0.85rem; height: 0.85rem; display: block; transition: transform 0.15s ease; } .pane.closed .pane-toggle svg { transform: rotate(-90deg); } .pane-head h2 { cursor: pointer; } .pane { background: var(--fc-snow); border: 1px solid var(--fc-line); display: flex; flex-direction: column; min-height: 0; } .pane h2 { margin: 0; padding: 0.45rem 0.75rem; border-bottom: 1px solid var(--fc-line); font-size: 0.7rem; } .pane-body { flex: 1 1 auto; overflow: auto; padding: 0.75rem; min-height: 0; } .pane-sql .pane-body { padding: 0; } .empty { color: var(--fc-slate); font-size: 0.85rem; margin: 0; } .empty.fail { color: var(--fc-alert); white-space: pre-wrap; } .chart-body { position: relative; } .chart-body canvas { width: 100% !important; height: 100% !important; } .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100%; color: var(--fc-slate); font-size: 0.9rem; text-align: center; margin: 0; } #chart-empty.fail #empty-copy { color: var(--fc-alert); white-space: pre-wrap; } .empty-state[hidden], canvas[hidden], .empty-state img[hidden] { display: none; } .empty-state img { width: 10rem; height: 10rem; object-fit: contain; margin-bottom: 0.75rem; } /* Dots hide via visibility so the centred copy never shifts as they cycle. */ .run-dots span { visibility: hidden; } .run-dots span.on { visibility: visible; } @media (prefers-reduced-motion: reduce) { #waiting-cat { animation: none; } .pane-toggle svg { transition: none; } } #sql { margin: 0; min-height: 100%; box-sizing: border-box; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; font-size: 0.78rem; } code.fc-sql { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; font-size: 0.92em; font-weight: 650; background: var(--fc-ochre-wash); padding: 0.08em 0.28em; border-radius: 0.2rem; } html[data-vocab="sql"] .series-measure, html[data-vocab="sql"] .filter-op, html[data-vocab="sql"] #measure { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace; font-size: 0.78rem; } .summary { font-size: 0.75rem; color: var(--fc-slate); margin: 0 0 0.75rem; } .pane-head { display: flex; align-items: center; justify-content: flex-start; gap: 0.5rem; padding-right: 0.5rem; } .pane-head .pane-actions { margin-left: auto; } .pane-head h2 { padding-left: 0; } .pane-head h2 { border-bottom: none; padding: 0.45rem 0.75rem; } .pane-actions { display: flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; } .pane-actions button, .pane-actions select { margin: 0; padding: 0.2rem 0.5rem; font-size: 0.7rem; width: auto; } .pane-actions label { margin: 0; font-weight: 400; display: flex; align-items: center; gap: 0.25rem; } .chart-title { flex: 1; min-width: 8rem; margin: 0; padding: 0.35rem 0.75rem; border: none; border-bottom: 1px solid var(--fc-line); font-size: 0.8rem; font-weight: 600; background: transparent; } #exact-wrap[hidden] { display: none !important; } #run-row { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.75rem; flex-wrap: wrap; } #run-row button { margin-top: 0; } #run-estimate, #table-count { font-size: 0.8rem; color: var(--fc-slate); } #run-estimate-wrap { display: inline-flex; align-items: center; gap: 0.4rem; } #run-estimate-wrap[hidden] { display: none !important; } #run-estimate-bar[hidden] { display: none !important; } #run-estimate-bar { display: inline-block; width: 3.2rem; height: 0.45rem; background: var(--fc-line); border-radius: 2px; overflow: hidden; vertical-align: middle; } #run-estimate-fill { display: block; height: 100%; width: 0; background: var(--fc-ok); } #run-estimate-wrap.warn #run-estimate-fill { background: var(--fc-ochre); } #run-estimate-wrap.hot #run-estimate-fill, #run-estimate-wrap.over-cap #run-estimate-fill { background: var(--fc-alert); } #run-estimate-wrap.over-cap #run-estimate { color: var(--fc-alert); font-weight: 600; } /* Managed tables: cost, reason, next-run cost — in plain words. A child of the (wrapping) toolbar, NOT of #run-row: inside the run row its text width inflated the row's intrinsic size and wrapped the whole row under the date controls, moving Run. As the toolbar's last child with a 100% basis it takes its own line and moves nothing. */ /* One short line after a run that indexed (or failed to): its own toolbar line, right-aligned under the chip and Run, capped so long text wraps from the right and never spans the toolbar. */ #run-note { flex: 1 1 100%; display: flex; justify-content: flex-end; margin: 0; } #run-note > span { max-width: 32rem; text-align: right; font-size: 0.75rem; color: var(--fc-slate); } #run-note.ochre > span { color: var(--fc-ochre-deep); } #run-note[hidden] { display: none !important; } .format-pop { position: relative; font-size: 0.7rem; } .format-pop > summary { cursor: pointer; list-style: none; padding: 0.2rem 0.5rem; border: 1px solid var(--fc-line); border-radius: 0.2rem; } .format-pop > summary::-webkit-details-marker { display: none; } .format-pop[open] > .format-body { position: absolute; right: 0; top: calc(100% + 0.2rem); z-index: 8; background: var(--fc-snow); border: 1px solid var(--fc-line); padding: 0.65rem 0.75rem; min-width: 14rem; box-shadow: 0 4px 14px rgba(28, 25, 23, .08); } .format-body label { display: flex; justify-content: space-between; align-items: center; gap: 0.6rem; margin: 0.4rem 0; font-weight: 400; font-size: 0.7rem; } .format-body select { width: auto; font-size: 0.7rem; padding: 0.15rem 0.3rem; } .icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 1.75rem; height: 1.75rem; padding: 0; margin: 0; background: var(--fc-snow); border: 1px solid var(--fc-line); border-radius: 0.25rem; cursor: pointer; color: var(--fc-slate); } .icon-btn svg { width: 0.95rem; height: 0.95rem; display: block; } .icon-btn:hover { color: var(--fc-ink); border-color: var(--fc-ochre); } .icon-btn.copied { color: var(--fc-ok); border-color: var(--fc-ok); } .format-pop > summary.icon-btn { list-style: none; } .format-pop > summary.icon-btn::-webkit-details-marker { display: none; } .format-pop[hidden] { display: none !important; } /* One geometry for every icon control in a pane head. Outranks both ".pane-actions button" (hits copy buttons) and ".format-pop > summary" (hits download/format summaries), which disagree with .icon-btn. */ .pane-actions button.icon-btn, .pane-actions .format-pop > summary.icon-btn { box-sizing: border-box; width: 1.75rem; height: 1.75rem; padding: 0; border-radius: 0.25rem; } /* The global `details` rule adds margin-top: 0.75rem; inside a centred flex row that rides the popover 6px below its neighbours. */ .pane-actions details { margin: 0; } /* Export chrome is always visible; no content = disabled, never hidden. */ .icon-btn:disabled { color: var(--fc-slate); } .icon-btn:disabled:hover { color: var(--fc-slate); border-color: var(--fc-line); } .format-pop.disabled > summary { opacity: 0.55; cursor: not-allowed; pointer-events: none; } .format-pop[open] > .export-body { position: absolute; right: 0; top: calc(100% + 0.2rem); z-index: 8; background: var(--fc-snow); border: 1px solid var(--fc-line); padding: 0.25rem; min-width: 11rem; box-shadow: 0 4px 14px rgba(28, 25, 23, .08); display: flex; flex-direction: column; gap: 0.1rem; } .export-body button { margin: 0; padding: 0.35rem 0.6rem; width: 100%; background: none; border: 0; border-radius: 0.25rem; color: var(--fc-ink); font-size: 0.72rem; text-align: left; cursor: pointer; } .export-body button:hover { background: var(--fc-paper); } .pane-limit { display: flex; align-items: center; gap: 0.3rem; margin: 0; font-size: 0.7rem; font-weight: 400; color: var(--fc-slate); } .pane-limit input { width: 3.5rem; padding: 0.15rem 0.3rem; font-size: 0.7rem; } #cap-override { display: flex; align-items: center; gap: 0.35rem; font-size: 0.75rem; color: var(--fc-alert); } #cap-override[hidden] { display: none !important; } #result-table { table-layout: fixed; width: 100%; } #result-table th { position: relative; cursor: pointer; user-select: none; min-width: 4rem; border-right: 1px solid var(--fc-line); padding-right: 0.9rem; } #result-table th .sort { font-size: 0.65rem; color: var(--fc-slate); margin-left: 0.25rem; } #result-table th.sorted .sort { color: var(--fc-ink); } #result-table th .grip { position: absolute; right: 0; top: 0; width: 8px; height: 100%; cursor: col-resize; background: linear-gradient(to right, transparent 2px, var(--fc-slate) 2px, var(--fc-slate) 3px, transparent 3px); } #result-table th .grip:hover { background: var(--fc-ochre); } .range-row { display: flex; gap: 0.4rem; align-items: center; margin-top: 0.35rem; } .range-row[hidden], .toolbar-cluster[hidden], #range-include[hidden], #custom-range[hidden], #custom-absolute[hidden], #custom-relative[hidden], #range_n_unit_select[hidden], #rel_unit_select[hidden], #range_n_unit[hidden], #rel_unit_label[hidden] { display: none !important; } .range-row input[type="number"] { width: 4.5rem; } #breakdown-extra[hidden] { display: none !important; } #breakdown-extra .range-row { margin-top: 0.5rem; } .fc-plus { display: inline-flex; align-items: center; justify-content: center; width: 1.65rem; height: 1.65rem; margin: 0; padding: 0; background: var(--fc-snow); color: var(--fc-ochre-deep); border: 1px solid var(--fc-line); border-radius: 999px; cursor: pointer; box-shadow: 0 1px 0 rgba(28, 25, 23, 0.06); } .fc-plus:hover { border-color: var(--fc-ochre); color: var(--fc-ink); background: var(--fc-paper); } .fc-plus svg { width: 0.82rem; height: 0.82rem; display: block; } .fc-plus-row { display: flex; justify-content: center; align-items: center; margin: 0.3rem 0 0.05rem; } .event-group-members .fc-plus-row { margin: 0.2rem 0; } .fc-or { display: flex; align-items: center; gap: 0.55rem; margin: 0.1rem 0.4rem; color: var(--fc-slate); font-size: 0.68rem; font-weight: 600; letter-spacing: 0.08em; user-select: none; } .fc-or::before, .fc-or::after { content: ""; flex: 1; height: 1px; background: var(--fc-line); } #add-breakdown-row[hidden], #add-event-row[hidden], .fc-plus-row[hidden] { display: none !important; } .breakdown-slot-head { margin: 0.65rem 0 0.2rem; } .breakdown-slot-head label { margin: 0; } .breakdown-slot-row, .series-bd-slot:not(:first-child) .series-bd-row { display: flex; align-items: center; gap: 0.45rem; } .breakdown-slot-row select, .series-bd-slot:not(:first-child) .series-bd-row select { flex: 1; min-width: 0; width: auto; margin: 0; } .breakdown-slot-row .linkish, .series-bd-slot:not(:first-child) .series-bd-row .linkish { margin: 0; flex: 0 0 auto; } /* Same card surface as .event-card (border/background/padding values reused verbatim); nested series slots take the .event-group-members .event-card snow background, the shipped card-in-card treatment. */ #breakdown-chart .breakdown-slot, .series-bd-slot { border: 1px solid var(--fc-line); background: var(--fc-paper); padding: 0.5rem 0.55rem 0.4rem; margin: 0 0 0.5rem; min-width: 0; } /* The toggle row above sits flush (0px) otherwise — invisible before the cards drew a border there. Same 0.5rem rhythm as the seams. */ #breakdown-chart .breakdown-slot[data-slot="0"] { margin-top: 0.5rem; } .series-bd-slot { background: var(--fc-snow); margin: 0 0 0.35rem; } .bd-value-controls { margin-top: 0.3rem; } .bd-value-controls[hidden], .bd-fill-wrap[hidden], .bd-fill-expr-wrap[hidden], .bd-value-pair[hidden], #bd-null-nudge[hidden] { display: none !important; } .bd-value-row { display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: flex-start; } .bd-value-pair { display: flex; flex-direction: column; flex: 1 1 9rem; min-width: 7rem; } /* Two-class chains so these beat .series-bd label (0,1,1, later in the file); descendant (not >) so the SQL-expression label inside .bd-fill-expr-wrap is owned here too. */ .bd-value-controls .bd-value-pair label, .bd-value-controls .bd-fill-wrap label, .bd-value-controls .bd-fill-expr-wrap label { margin: 0; font-size: 0.7rem; font-weight: 600; } .bd-value-pair select { width: auto; font-size: 0.75rem; margin: 0; } .bd-fill-wrap { margin-top: 0.3rem; display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; } .bd-fill-wrap select, .bd-fill-wrap input { /* min-width 0 lets flex shrink the select below its widest option (long event names) so a 256px column never scrolls sideways. */ width: auto; flex: 1 1 8rem; min-width: 0; font-size: 0.75rem; margin: 0; } /* Column flex so the label and input stretch to the wrap's width; the input opts back out of the row rule above (flex-basis would become HEIGHT in a column context) and takes the full line. */ .bd-fill-expr-wrap { flex: 1 1 100%; display: flex; flex-direction: column; } /* Two-class chain: beats .bd-fill-wrap input on specificity, not source order — the same convention as the label chains above. */ .bd-fill-wrap .bd-fill-expr-wrap input { flex: 0 0 auto; width: 100%; } #bd-null-nudge { margin-top: 0.35rem; } #bd-null-nudge .linkish { margin-left: 0; } .series-bd .remove-breakdown { margin-left: 0.4rem; } #of-wrap[hidden] { display: none !important; } /* Section panels (non-collapsing; heads are static — no pane classes, whose head click listener and margins must not reach this column). */ .cfg-section { border: 1px solid var(--fc-line); background: var(--fc-snow); margin: 0 0 .75rem; } .cfg-section-head { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .4rem .55rem; border-bottom: 1px solid var(--fc-line); font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--fc-ink-soft); } .cfg-section-head .linkish { text-transform: none; letter-spacing: 0; } /* The head must not re-case folded SQL against the user's sql_case preference. */ .cfg-section-head code.fc-sql { text-transform: none; letter-spacing: 0; } .cfg-section-body { padding: .5rem .55rem .45rem; min-width: 0; } .cfg-section-body > .row:first-child { margin-top: 0; } /* Seams: adjacent vertical margins COLLAPSE (the larger wins, they do not add). Exact hidden (the first-run default): section bottom .75rem meets the next section = 12px. Exact shown: .75rem meets #exact-wrap's .75rem on both sides = 12px above and below. The inner .row's global margin-top is zeroed so it cannot collapse through and silently become the seam's owner. */ #exact-wrap { margin: .75rem 0; } #exact-wrap .row { margin-top: 0; } .cfg-section-title { min-width: 0; } .cfg-section-actions { display: flex; align-items: center; gap: 0.75rem; flex: 0 0 auto; } .cfg-section-actions .linkish { margin-left: 0; } .refresh-split { display: inline-flex; align-items: center; } .refresh-split .refresh-more { margin-left: 0.35rem; padding-left: 0.35rem; border-left: 1px solid var(--fc-line); text-decoration: none; line-height: 1; display: inline-flex; align-items: center; } .refresh-split .refresh-more svg { width: 0.7rem; height: 0.7rem; display: block; } .refresh-split .refresh-more[aria-expanded="true"] svg { transform: rotate(180deg); } #find-event[hidden], #find-event-panel[hidden], #event-names-snapshot[hidden], #event-names-status[hidden], #event-names-fallback[hidden] { display: none !important; } #event-names-fallback { margin: 0 0 0.35rem; } #find-event-panel { margin: 0 0 0.45rem auto; padding: 0.15rem 0 0.25rem; width: max-content; max-width: 100%; text-align: left; } .find-event-opt { display: block; width: 100%; margin: 0; padding: 0.25rem 0; border: 0; background: none; color: var(--fc-ochre-deep); font-size: 0.75rem; text-align: left; cursor: pointer; } .find-event-opt:hover { text-decoration: underline; } .find-event-opt .hint { margin: 0.1rem 0 0; } .catalog-status { font-weight: 400; color: var(--fc-slate); font-size: 0.7rem; margin: 0 0 0.35rem; } #event-names-snapshot { margin: 0 0 0.35rem; } .fc-plus-labeled { display: flex; align-items: center; justify-content: center; gap: 0.4rem; width: 100%; margin: 0.35rem 0 0; padding: 0; background: none; border: none; color: var(--fc-ochre-deep); font: inherit; font-size: 0.75rem; font-weight: 500; cursor: pointer; } .fc-plus-labeled .fc-plus { cursor: inherit; box-shadow: none; } .fc-plus-labeled:hover { color: var(--fc-ink); } .fc-plus-labeled:hover .fc-plus { border-color: var(--fc-ochre); color: var(--fc-ink); background: var(--fc-paper); } .event-card, .event-group { border: 1px solid var(--fc-line); background: var(--fc-paper); padding: 0.5rem 0.55rem 0.4rem; margin: 0 0 0.5rem; } .event-group { padding-bottom: 0.5rem; } .event-card-head, .event-group-head { display: flex; align-items: center; gap: 0.35rem; } .event-card-head .event-card-name { flex: 1; margin: 0; min-width: 0; } .event-card-head .series-measure, .event-group-head .series-measure { flex: 0 1 11rem; width: auto; min-width: 7rem; margin: 0; font-size: 0.8rem; } .event-group-title { font-size: 0.75rem; font-weight: 600; color: var(--fc-slate); flex: 0 0 auto; } .event-card-filters { margin: 0.2rem 0 0; } .event-card-filters:has(.filter-line) { margin-left: 0.15rem; padding-left: 0.55rem; border-left: 2px solid var(--fc-line); } .filter-line { display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; margin-top: 0.3rem; } .filter-line select, .filter-line input { width: auto; flex: 1 1 5.5rem; font-size: 0.75rem; margin: 0; } .filter-line .filter-json[hidden], .filter-line .filter-expr[hidden], .filter-line .filter-op[hidden], .filter-line .filter-value[hidden], .filter-line .filter-value-to[hidden], .filter-line .filter-value-time[hidden], .filter-line .filter-value-to-time[hidden], .filter-line .filter-case[hidden], .filter-line .filter-pills[hidden], .filter-line .filter-part[hidden], .filter-line .filter-enum[hidden], .filter-line .filter-period[hidden], .filter-line .filter-period-to[hidden] { display: none !important; } .filter-period, .filter-period-to { display: inline-flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; } .filter-week-n, .filter-week-n-to { width: 4.2rem; flex: 0 0 4.2rem; } .filter-quarter-q, .filter-quarter-q-to { width: auto; flex: 0 0 auto; } .filter-part { flex: 0 1 8.5rem; min-width: 7rem; } .filter-pills { display: flex; flex-wrap: wrap; gap: 0.25rem; align-items: center; flex: 1 1 12rem; min-width: 8rem; border: 1px solid var(--fc-line); background: var(--fc-snow); padding: 0.15rem 0.3rem; min-height: 1.75rem; } .filter-pill { display: inline-flex; align-items: center; gap: 0.15rem; max-width: 12rem; padding: 0.05rem 0.15rem 0.05rem 0.4rem; background: var(--fc-paper); border: 1px solid var(--fc-line); font-size: 0.7rem; line-height: 1.2; } .filter-pill > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .filter-pill button { background: none; border: none; padding: 0 0.15rem; margin: 0; cursor: pointer; color: var(--fc-slate); font-size: 0.85rem; line-height: 1; } .filter-pill button:hover { color: var(--fc-ink); } .filter-line .filter-pills-input { flex: 1 1 5rem; min-width: 5rem; width: auto; margin: 0; padding: 0.15rem 0; border: none; background: transparent; font-size: 0.75rem; } .filter-line .filter-pills-input:focus { outline: none; } .filter-case { display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.7rem; font-weight: 400; margin: 0; flex: 0 0 auto; } .filter-case input { width: auto; margin: 0; flex: none; } .filter-line input[type="date"], .filter-line input[type="time"], .filter-line input[type="number"] { flex: 0 1 8rem; } .event-group-members .event-card { background: var(--fc-snow); margin: 0; } .card-actions { margin-top: 0.35rem; } .add-card-filter { margin: 0.2rem 0 0 0; } .series-bd { margin-top: 0.45rem; } .series-bd[hidden], #breakdown-chart[hidden] { display: none !important; } .series-bd label { font-size: 0.75rem; font-weight: 400; } #chart-measure-template[hidden] { display: none !important; } .series-of { margin: 0.35rem 0 0; } .series-of[hidden] { display: none !important; } .series-of-json[hidden], .series-of-expr[hidden] { display: none !important; } .series-bd-json[hidden], .series-bd-expr[hidden] { display: none !important; } #event_value-wrap[hidden] { display: none !important; } #top_n { width: 4.5rem; } .incomplete-note { font-size: 0.75rem; color: var(--fc-slate); margin: 0.35rem 0 0; } .stale-note { font-size: 0.75rem; color: var(--fc-ochre-deep); margin: 0 0 0.5rem; } .stale-note[hidden] { display: none !important; } #result-table tr.incomplete td { color: var(--fc-slate); font-style: italic; } #custom-snap-hint { margin: 0.35rem 0 0; } .event-card-filters .add-card-filter { margin: 0.2rem 0 0 0; } {% endblock %} {% block body %}

Events

{% if not mapping_ready %}

Map a table on Setup before Events can run.

{% endif %}

{{ config.table }} · {{ config.entity_label or "User" }} ({{ config.entity }}) · {{ config.event_time }}

Event series
Same bytes scanned; more CPU. Off is HyperLogLog (faster).
{{ filter_ui.chrome.bd_section | sql_chrome }}

{% if mapping_ready %}No rows yet. The cat is waiting.{% else %}Map a table on Setup before Events can run.{% endif %}

Table

Run to fill the table.

SQL

SQL updates as you change the form.
{% endblock %}