.filters {
    display: grid;
    grid-row: auto auto;
    /* Without minmax(0, …) the implicit column is sized to its widest child's
       min-content, so the whole dashboard grew past a 360px phone. */
    grid-template-columns: minmax(0, 1fr);
    width: 100%;
}

.filters > * {
    min-width: 0;
}

.current-visitors {
    margin-bottom: 10px;
}

.live-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    background-color: rgb(34, 197, 94);
    border-radius: 50%;
    margin-right: 5px;
    position: relative;
}

.live-dot::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 10px;
    height: 10px;
    transform: translate(-50%, -50%) scale(1);
    border-radius: 50%;
    background-color: rgb(34, 197, 94);
    animation: radar-pulse 2s ease-out infinite;
}

@keyframes radar-pulse {
    0% {
        transform: translate(-50%, -50%) scale(1);
        opacity: 0.8;
    }
    100% {
        transform: translate(-50%, -50%) scale(3);
        opacity: 0;
    }
}

.top-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px 16px;
    margin-bottom: 20px;
    width: 100%;
}

.custom-date {
    display: flex;
    align-items: center;
    min-width: 0;
}

.export-csv-link {
    margin-left: auto;
}

.date-dropdown label {
    margin-right: 10px;
}

.or {
    margin: 10px;
}

.date-select, .date-input {
    -webkit-appearance: none;  
    appearance: none;
    padding: 8px 13px;
    border: 1px solid #e0e0e0;
    border-radius: 6px;
    font-size: 14px;
    background-color: white;
    color: inherit;
    box-sizing: border-box;
    min-height: 35px;
}

.metric-boxes {
    display: grid;
    /* minmax(0, 1fr), not 1fr: a bare `1fr` floors at the item's min-content
       width, so six tiles could refuse to shrink and push the whole dashboard
       sideways. Measured at 1024px with production data, the six columns froze
       at 683.5px + 100px of gap = 783.5px inside a 694px box and the page
       scrolled to 1084. See the 3-column band below. */
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 20px;
    margin-bottom: 30px;
    width: 100%;
}

.metric-box {
    background: var(--color-white);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    padding: 20px;
    cursor: pointer;
    transition: all 0.3s ease;
    /* Grid items default to min-width:auto (= min-content). This was set only
       inside the <=900px query, so between 900px and ~1113px the widest tile
       ("Views/Session", 141.1px min-content) held the grid open. */
    min-width: 0;
}

/* F-06: the six radios that switch the chart used to carry `hidden`, which
   takes an element out of the tab order AND out of the accessibility tree —
   the tiles were mouse-only, and a screen reader was never told the page had
   a metric choice at all. They are hidden the way a custom control's input
   must be: still rendered, still focusable, still announced, just not drawn.
   `opacity: 0` alone would leave a 1px target; `display: none`,
   `visibility: hidden` and `hidden` all take the focus away again. */
.metric-box input[name="filter"] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

/* The focus ring the input can no longer draw for itself. Without this the
   six tiles are reachable but the caret is invisible on them — F-10 on the
   metric row. */
.metric-box:focus-within {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* Six tiles need ~783.5px of grid content. How soon that is available depends
   on whether the sidebar is there, so the reflow band does too — measured
   `gridWidth = viewport - 330` with the sidebar and `viewport - 180` without
   it, putting the six-across threshold at ~1113px and ~964px respectively.
   Getting this wrong is not a crash, it is a quieter cost: an unscoped
   901-1150px band made the PUBLIC demo — the page /demo sends prospects to —
   render 3 + 3 at 1024px where all six fit comfortably.

   Note the division of labour. These bands decide what looks right; they are
   not what keeps the page safe. `minmax(0, 1fr)` plus the global
   `min-width: 0` above mean an unexpectedly wide metric value is clipped by
   the existing `.metric-value` ellipsis rule rather than scrolling the whole
   dashboard sideways, at any width, whatever the data. */
@media screen and (min-width: 901px) and (max-width: 1150px) {
    .container:not(.no-sidebar) .metric-boxes {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        row-gap: 12px;
    }
}

@media screen and (min-width: 901px) and (max-width: 970px) {
    .container.no-sidebar .metric-boxes {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        row-gap: 12px;
    }
}

.metric-box:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.metric-box.active {
    border-color: var(--color-primary);
    background-color: rgba(38, 98, 163, 0.05);
}

.metric-title {
    font-size: 14px;
    color: var(--color-text-secondary);
    margin-bottom: 8px;
}

.metric-value {
    font-size: 24px;
    font-weight: 600;
    color: #333;
}

@media screen and (max-width: 900px) {
    .top-bar {
        display: flex;
        flex-direction: column;
        row-gap: 10px;
        width: 100%;
        margin-bottom: 15px;
    }

    .date-dropdown {
        display: flex; /* Use flexbox for layout */
        align-items: center; /* Center items vertically */
        width: 100%; /* Ensure it takes full width */
    }
    
    .date-select {
        flex: 1; /* Allow the select to take all available space */
        width: 100%;
    }

    .date-input {
        width: 100%;
    }

    .custom-date {
        width: 100%;
        text-align: center; /* Center the content horizontally */
        display: flex; /* Use flexbox for centering */
        justify-content: center; /* Center the items horizontally */
        align-items: center; /* Center the items vertically */
    }

    /* Two <input type=date> have a ~205px intrinsic minimum each, so a
       width:100% pair forced a 445px row and pushed the whole dashboard wider
       than the phone. flex-basis 0 + min-width 0 lets them shrink to fit. */
    .custom-date .date-input {
        flex: 1 1 0;
        min-width: 0;
        width: auto;
    }

    .custom-date .or {
        margin: 0 8px;
        flex: 0 0 auto;
    }

    .export-csv-link {
        margin-left: 0;
    }

    .metric-boxes {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        row-gap: 10px;
        column-gap: 10px;
        margin-bottom: 15px;
    }

    .metric-box {
        padding: 10px 20px; /* Set top and bottom padding to 10px, left and right remains 20px */
        /* min-width: 0 is global now — it was needed above 900px too. */
    }

    .metric-value, .metric-title {
        overflow: hidden;
        text-overflow: ellipsis;
    }
}

/* Border beam: a blue light tracing the active box's perimeter while its
   data is in flight. The conic gradient spins via the registered --beam-angle
   custom property; the two-layer mask keeps only the 2px border ring. */
@property --beam-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}

.metric-box {
    position: relative;
}

.metric-box.loading::before {
    content: '';
    position: absolute;
    inset: -2px;
    border-radius: 12px;
    padding: 2px;
    background: conic-gradient(from var(--beam-angle),
        transparent 0deg 290deg,
        var(--color-secondary-xlight) 315deg,
        var(--color-secondary) 340deg,
        var(--color-primary) 360deg);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    animation: beam-spin 1.1s linear infinite;
    pointer-events: none;
}

@keyframes beam-spin {
    to { --beam-angle: 360deg; }
}

@media (prefers-reduced-motion: reduce) {
    .metric-box.loading::before {
        background: conic-gradient(var(--color-primary), var(--color-secondary), var(--color-primary));
        animation: beam-pulse 1.6s ease-in-out infinite;
    }

    @keyframes beam-pulse {
        0%, 100% { opacity: 0.25; }
        50% { opacity: 0.8; }
    }
}

/* Compare-to-previous-period: checkbox in the top bar, dashed overlay on the
   chart, delta badges under the metric values (hidden when compare is off). */
.compare-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    color: var(--color-text-secondary);
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.compare-toggle input {
    accent-color: var(--color-primary);
    cursor: pointer;
    margin: 0;
}

.metric-delta {
    font-size: 12px;
    margin-top: 4px;
    color: var(--color-text-secondary);
    min-height: 14px;
}

.metric-delta.up {
    color: #166534;
}

.metric-delta.down {
    color: #b91c1c;
}

body.compare-off .metric-delta {
    visibility: hidden;
}

@media screen and (max-width: 900px) {
    .compare-toggle {
        justify-content: center;
        width: 100%;
    }

    .metric-delta {
        margin-top: 2px;
        min-height: 12px;
    }
}

/* Old numbers stay readable while fresh ones load. */
body.data-loading .chart-wrapper,
body.data-loading .data-container-2,
body.data-loading .data-container-3 {
    opacity: 0.55;
    transition: opacity 0.15s ease;
}

/* Export menu: the old single link, now opening a small dataset list. */
.export-menu {
    margin-left: auto;
    position: relative;
}

.export-menu summary {
    cursor: pointer;
    list-style: none;
}

.export-menu summary::-webkit-details-marker {
    display: none;
}

.export-menu summary::after {
    content: ' \25BE';
    font-size: 11px;
}

.export-menu-list {
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    z-index: 100;
    min-width: 185px;
    padding: 6px;
    background: var(--color-white);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
    display: flex;
    flex-direction: column;
}

.export-menu-list a {
    padding: 7px 10px;
    border-radius: 6px;
    font-size: 14px;
    color: var(--color-text);
    text-decoration: none;
    white-space: nowrap;
}

.export-menu-list a:hover {
    background: rgba(50, 141, 204, 0.08);
    color: var(--color-primary);
}

@media screen and (max-width: 900px) {
    .export-menu {
        margin-left: 0;
    }

    .export-menu-list {
        right: auto;
        left: 0;
    }
}
/* iOS Safari zooms into any focused form control whose font-size is under
   16 px, and does not zoom back out — so picking a date range on an iPhone
   left the dashboard zoomed and scrolling sideways, which is the exact
   symptom the 0.8 phone pass existed to remove. The date inputs, the range
   select and the badge selects were all 13–14 px.
   16 px is the fix that keeps pinch-zoom available; `maximum-scale=1` would
   also stop the zoom, by taking zoom away from everyone. */
@media screen and (max-width: 900px) {
    /* The class names are load-bearing, not decoration: `.date-select` and
       `.date-input` set 14px at (0,1,0), which beats a bare `input`/`select`
       type selector however late it appears — the first version of this rule
       shipped and changed nothing at all. Verified on the live dashboard: 3
       controls under 16px before, 0 after. */
    .date-select,
    .date-input,
    input,
    select,
    textarea {
        font-size: 16px;
    }
}

/* The report line is a screen-reader announcement (role=status) while a range
   loads or succeeds; the dates are already on the chart. It shows only when
   something went wrong, next to Retry. */
.report-status-row {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px 10px;
    margin: 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--text-muted, #6b7280);
}
.report-status-row:has(#report-status[data-state="error"]),
.report-status-row:has(#report-status[data-state="invalid"]) { margin: 8px 0 12px; }
#report-status:not([data-state="error"]):not([data-state="invalid"]) {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}
#retry-report {
    font: inherit;
    color: var(--link-color, #2675ac);
    background: transparent;
    border: 0;
    padding: 6px 8px;
    cursor: pointer;
    text-decoration: underline;
}
#retry-report[hidden] { display: none; }
#retry-report:focus-visible { outline: 2px solid #2675ac; outline-offset: 2px; }
