/* Dashboard styling. Deliberately small and dependency-free — the template's Bootstrap and jQuery
   were removed, since a two-card internal tool does not need a CSS framework. */

:root {
    --bg: #f5f6f8;
    --card: #ffffff;
    --ink: #1c1f23;
    --ink-soft: #6b7280;
    --line: #e3e6ea;
    --accent: #2f6fd0;
    --ok: #2f8f4e;
    --bad: #c0392b;
    --radius: 10px;
    --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .1);
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #14171a;
        --card: #1d2126;
        --ink: #e8eaed;
        --ink-soft: #9aa3ad;
        --line: #2c3239;
        --accent: #5b9bf5;
        --ok: #4cae6a;
        --bad: #e06455;
        --shadow: none;
    }
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 24px;
    background: var(--card);
    border-bottom: 1px solid var(--line);
}

.brand { font-weight: 650; letter-spacing: -.01em; }

.logout-form { display: flex; align-items: center; gap: 12px; }
.who { color: var(--ink-soft); font-size: 13px; }

.link-button {
    background: none;
    border: 0;
    color: var(--accent);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    padding: 0;
}

main {
    /* Wider than the old 1200px by exactly the sidebar plus its gap, so the revenue cards keep the
       width they had and the bookmarks card occupies what used to be blank margin. */
    max-width: 1500px;
    margin: 0 auto;
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* Sidebar left, revenue right. The main column is first in the markup because it is the primary
   content; explicit column placement puts the aside on the left without reordering the source. */
.dashboard-grid {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    gap: 20px;
    align-items: start;
}

.main-column {
    grid-column: 2;
    display: flex;
    flex-direction: column;
    gap: 20px;
    /* minmax(0,1fr) above plus this stops the chart canvas forcing the column wider than its
       share — a grid item's default min-width:auto would let it push the sidebar off-screen. */
    min-width: 0;
}

.side-column {
    grid-column: 1;
    grid-row: 1;
    /* Follows the page rather than the viewport: the card is short, and pinning it would leave a
       large gap beside a tall chart. */
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* Below this the sidebar has nowhere useful to go, so everything stacks and the bookmarks card
   lands under the revenue cards — its source position. */
@media (max-width: 1100px) {
    .dashboard-grid { grid-template-columns: minmax(0, 1fr); }
    .main-column, .side-column { grid-column: 1; }
    .side-column { grid-row: auto; }
}

.card {
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 20px 24px;
}

/* ── Headliner ────────────────────────────────────────────────────────────── */

.headliner {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.figures {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
}

.figure { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.figure .label {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--ink-soft);
}

.figure .value {
    font-size: 30px;
    font-weight: 650;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}

.figure .sub { font-size: 12px; color: var(--ink-soft); }

.figure.estimate .value { color: var(--ink-soft); }

.hint {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--line);
    color: var(--ink-soft);
    font-size: 10px;
    cursor: help;
    vertical-align: middle;
}

.headliner-actions {
    display: flex;
    align-items: center;
    gap: 14px;
    padding-top: 4px;
    border-top: 1px solid var(--line);
    margin-top: 4px;
}

.sync-status { font-size: 13px; color: var(--ink-soft); }

button.primary {
    background: var(--accent);
    color: #fff;
    border: 0;
    border-radius: 6px;
    padding: 8px 14px;
    font: inherit;
    font-size: 14px;
    font-weight: 550;
    cursor: pointer;
}

button.primary:hover:not(:disabled) { filter: brightness(1.08); }
button.primary:disabled { opacity: .55; cursor: default; }

/* The 7-day refresh. Same shape as primary but outlined rather than filled: it is the one you
   press most often, and two filled buttons side by side would compete for the same emphasis. */
button.secondary {
    background: none;
    color: var(--accent);
    border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
    border-radius: 6px;
    padding: 8px 14px;
    font: inherit;
    font-size: 14px;
    font-weight: 550;
    cursor: pointer;
}

button.secondary:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 10%, transparent); }
button.secondary:disabled { opacity: .55; cursor: default; }

/* ── Integration chips ────────────────────────────────────────────────────── */

/* One chip per integration, always all of them. Colour carries the state; the dot repeats it so
   the meaning does not rest on colour alone. */
.chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding-top: 12px;
    border-top: 1px solid var(--line);
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font: inherit;
    font-size: 13px;
    font-weight: 500;
    padding: 6px 12px;
    border-radius: 20px;
    border: 1px solid var(--line);
    background: none;
    color: var(--ink-soft);
    text-decoration: none;
    white-space: nowrap;
    cursor: default;
}

.chip-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.chip.ok {
    color: var(--ok);
    border-color: color-mix(in srgb, var(--ok) 35%, transparent);
    background: color-mix(in srgb, var(--ok) 8%, transparent);
}

.chip.error {
    color: var(--bad);
    border-color: color-mix(in srgb, var(--bad) 45%, transparent);
    background: color-mix(in srgb, var(--bad) 10%, transparent);
}

/* Not a fault — just not switched on. Muted so it reads as absent rather than broken. */
.chip.disabled {
    color: var(--ink-soft);
    border-color: var(--line);
    opacity: .65;
}

button.chip, a.chip { cursor: pointer; }
button.chip:hover, a.chip:hover { filter: brightness(1.06); }
button.chip.ok:hover { background: color-mix(in srgb, var(--ok) 16%, transparent); }
button.chip.error:hover, a.chip.error:hover { background: color-mix(in srgb, var(--bad) 18%, transparent); }

/* ── Sync step states ─────────────────────────────────────────────────────────
   Applied only while a run is in flight, on top of the chip's ok/error/disabled
   colour. Each chip is one step, so the row doubles as the progress display and
   the status line never has to name which providers are running concurrently. */

/* Queued but not started. Dimmed rather than recoloured, so the row still reads
   as a plan rather than as six broken integrations. */
.chip.step-waiting { opacity: .45; }

.chip.step-running {
    color: var(--accent);
    border-color: color-mix(in srgb, var(--accent) 45%, transparent);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    opacity: 1;
}

.chip.step-running .chip-dot { animation: chip-pulse 1s ease-in-out infinite; }

/* Done and failed deliberately keep the chip's own ok/error colour — the tick and
   cross carry the outcome, and recolouring would fight the health state. */
.chip.step-done .chip-dot,
.chip.step-failed .chip-dot { animation: none; }

.chip.step-done::after {
    content: '✓';
    font-size: 11px;
    opacity: .85;
}

.chip.step-failed::after {
    content: '✕';
    font-size: 11px;
    color: var(--bad);
}

/* Configured but not part of this run — a targeted chip sync leaves the rest here. */
.chip.step-skipped { opacity: .45; }

/* "47/90 days", on the chip doing the work. */
.chip-progress {
    font-variant-numeric: tabular-nums;
    font-size: 11px;
    font-weight: 600;
    opacity: .8;
    padding-left: 2px;
}

/* Pulses while its own sync is in flight. Kept for the optimistic click state,
   before the first poll comes back with real step phases. */
.chip.syncing { opacity: .6; }
.chip.syncing .chip-dot { animation: chip-pulse 1s ease-in-out infinite; }

@keyframes chip-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: .25; }
}

/* ── Chart ────────────────────────────────────────────────────────────────── */

.chart-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}

.filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* All three filters read as one control group, so they share a shell: same height, same border,
   same chevron. The period select previously had a transparent border and looked unstyled. */
.control,
.select-wrap select {
    font: inherit;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink);
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 7px 30px 7px 11px;
    height: 34px;
    cursor: pointer;
}

.control:hover,
.select-wrap select:hover { border-color: var(--ink-soft); }

.control:focus-visible,
.select-wrap select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.select-wrap { position: relative; display: inline-flex; align-items: center; }

.select-wrap select {
    appearance: none;
    -webkit-appearance: none;
}

/* A real chevron path rather than a text glyph — the ▾ character rendered thin and washed out. */
.chevron-icon {
    width: 9px;
    height: 9px;
    color: var(--ink-soft);
    flex: none;
    pointer-events: none;
}

.select-wrap .chevron-icon { position: absolute; right: 11px; }

/* ── Multi-select picker ──────────────────────────────────────────────────── */

.picker { position: relative; }

/* Padding is on .control; the chevron sits inside it like the select's does. */
.picker-button {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    position: relative;
    padding-right: 30px;
}

.picker-button .chevron-icon { position: absolute; right: 11px; }
.picker-button:hover .chevron-icon, .select-wrap select:hover + .chevron-icon { color: var(--ink); }

.picker-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 20;
    min-width: 240px;
    max-height: 320px;
    overflow-y: auto;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(16, 24, 40, .14);
    padding: 6px;
}

.picker-actions {
    display: flex;
    gap: 4px;
    padding: 2px 2px 6px;
    border-bottom: 1px solid var(--line);
    margin-bottom: 4px;
}

.picker-actions button {
    flex: 1;
    background: none;
    border: 0;
    font: inherit;
    font-size: 12px;
    color: var(--accent);
    padding: 4px;
    border-radius: 4px;
    cursor: pointer;
}

.picker-actions button:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }

.picker-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: 4px;
    font-size: 13px;
    cursor: pointer;
    white-space: nowrap;
}

.picker-option:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.picker-option input { cursor: pointer; margin: 0; }

.toggle {
    display: inline-flex;
    border: 1px solid var(--line);
    border-radius: 6px;
    overflow: hidden;
}

.toggle-option {
    background: none;
    border: 0;
    padding: 6px 14px;
    font: inherit;
    font-size: 13px;
    color: var(--ink-soft);
    cursor: pointer;
}

.toggle-option + .toggle-option { border-left: 1px solid var(--line); }
.toggle-option.active { background: var(--accent); color: #fff; }

/* Fixed height so Chart.js has a stable box to lay out against. */
.chart-holder { height: 380px; }

/* ── Breakdown table ──────────────────────────────────────────────────────── */

.breakdown {
    width: 100%;
    border-collapse: collapse;
    margin-top: 20px;
    font-size: 14px;
}

.breakdown th,
.breakdown td {
    padding: 8px 10px;
    text-align: left;
    border-bottom: 1px solid var(--line);
}

/* Right-aligned and tabular so the figures line up on the decimal. */
.breakdown .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Share is context, not the headline — muted so Total stays the figure your eye lands on. */
.breakdown .share { color: var(--ink-soft); font-size: 13px; }

.breakdown .change { font-size: 13px; color: var(--ink-soft); }
.breakdown .change.up { color: var(--ok); }
.breakdown .change.down { color: var(--bad); }

/* Narrow columns for the percentages so the label keeps the room it needs. */
.breakdown th:nth-child(2), .breakdown td:nth-child(2),
.breakdown th:nth-child(4), .breakdown td:nth-child(4) { width: 90px; }
.breakdown th:nth-child(3), .breakdown td:nth-child(3) { width: 110px; }

.breakdown thead th {
    padding: 0;
    border-bottom: 1px solid var(--line);
}

.breakdown thead button {
    width: 100%;
    background: none;
    border: 0;
    padding: 8px 10px;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ink-soft);
    cursor: pointer;
    text-align: inherit;
}

.breakdown thead th.num button { text-align: right; }
.breakdown thead button:hover { color: var(--ink); }

/* Arrow marks the active sort column and its direction. */
.breakdown thead th[aria-sort="ascending"] button::after { content: " ↑"; }
.breakdown thead th[aria-sort="descending"] button::after { content: " ↓"; }

.breakdown tbody tr:hover { background: color-mix(in srgb, var(--ink) 4%, transparent); }

/* Icons sit at text size and inherit colour, so they read as part of the label rather than as
   decoration bolted on beside it. */
.row-icon {
    width: 14px;
    height: 14px;
    flex: none;
    color: var(--ink-soft);
    vertical-align: -2px;
}

.breakdown td.with-icon { display: flex; align-items: center; gap: 8px; }
.picker-option .row-icon { width: 13px; height: 13px; }

/* Grouped rows: Apple and Google collapse their three categories behind one line. */
.breakdown tbody tr.group > td { padding: 0; }
.breakdown tbody tr.group > td.num { padding: 8px 10px; font-weight: 600; }

.group-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    background: none;
    border: 0;
    padding: 8px 10px;
    font: inherit;
    font-weight: 600;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

/* Trails the label rather than leading it, so every row's icon starts at the same x whether the
   row is expandable or not. */
.chevron {
    font-size: 10px;
    color: var(--ink-soft);
    flex: none;
    margin-left: 2px;
}

/* How many rows are hidden behind this one, so a collapsed group isn't a mystery. */
.group-count {
    font-size: 11px;
    font-weight: 500;
    color: var(--ink-soft);
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 0 6px;
    line-height: 16px;
}

/* Indented and muted so children read as belonging to the row above. */
.breakdown tbody tr.child > td:first-child {
    padding-left: 38px;
    color: var(--ink-soft);
}

/* Child icons sit slightly back so the parent's stays the anchor of the group. */
.breakdown tbody tr.child .row-icon { opacity: .6; }

.breakdown tbody tr.child > td { border-bottom-style: dashed; }

.breakdown tfoot th,
.breakdown tfoot td {
    border-bottom: 0;
    border-top: 2px solid var(--line);
    font-weight: 650;
}

.breakdown tfoot th { text-align: left; color: var(--ink-soft); font-weight: 550; }

/* ── Login ────────────────────────────────────────────────────────────────── */

.login-wrap { display: flex; justify-content: center; padding-top: 8vh; }

.login-card { width: 100%; max-width: 360px; display: flex; flex-direction: column; gap: 6px; }

.login-card h1 { margin: 0 0 12px; font-size: 20px; }

.login-card label {
    font-size: 12px;
    color: var(--ink-soft);
    margin-top: 8px;
}

.login-card input {
    padding: 9px 11px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--bg);
    color: var(--ink);
    font: inherit;
}

.login-card button { margin-top: 18px; }

.error {
    background: color-mix(in srgb, var(--bad) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--bad) 35%, transparent);
    color: var(--bad);
    border-radius: 6px;
    padding: 8px 10px;
    font-size: 13px;
    margin: 0 0 8px;
}

@media (max-width: 800px) {
    .figures { grid-template-columns: repeat(2, 1fr); }
    .chart-holder { height: 300px; }
}

/* ── Bookmarks ────────────────────────────────────────────────────────────────
   A plain list of links. The whole row is the link, with the edit and delete
   buttons layered on top — so the click target is the row, not a small anchor. */

.bookmarks-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.bookmarks-header h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--ink);
}

/* Stacked, not inline: at 300px two inputs and two buttons on one row leaves each of them
   unusably narrow. */
.bookmark-form {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-top: 14px;
}

.bookmark-form input {
    grid-column: 1 / -1;
    min-width: 0;
    font: inherit;
    font-size: 14px;
    padding: 8px 10px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--card);
    color: var(--ink);
}

.bookmark-form input:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -1px;
}

.bookmark-error {
    margin: 10px 0 0;
    font-size: 13px;
    color: var(--bad);
}

.bookmarks {
    list-style: none;
    margin: 14px 0 0;
    padding: 0;
}

.bookmarks li {
    display: flex;
    align-items: center;
    gap: 4px;
    border-top: 1px solid var(--line);
}

.bookmarks li:first-child { border-top: 0; }

/* The drag affordance. The whole row is draggable — this just says so. */
.bookmark-grip {
    display: inline-flex;
    align-items: center;
    flex: none;
    padding: 0 2px;
    color: var(--ink-soft);
    opacity: .35;
    cursor: grab;
}

.bookmarks li:hover .bookmark-grip { opacity: .7; }
.bookmarks li.dragging .bookmark-grip { cursor: grabbing; }
.bookmark-grip .row-icon { width: 11px; height: 11px; }

/* The row itself. Grows to fill so the whole width is clickable. */
.bookmark-link {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    min-width: 0;
    padding: 10px 4px;
    text-decoration: none;
    color: var(--ink);
    border-radius: 6px;
}

.bookmark-link:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }

.bookmark-link:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* Truncates rather than wraps: in a 300px column a long name would otherwise give one row three
   lines and push the buttons around. The full URL is on the row's tooltip. */
.bookmark-name {
    font-size: 14px;
    font-weight: 550;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bookmark-actions { display: flex; gap: 2px; flex: none; }

.bookmark-actions button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: none;
    color: var(--ink-soft);
    cursor: pointer;
}

.bookmark-actions button:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); color: var(--ink); }
.bookmark-actions button.delete:hover { background: color-mix(in srgb, var(--bad) 12%, transparent); color: var(--bad); }
.bookmark-actions .row-icon { width: 13px; height: 13px; }

/* The row being dragged. Kept in place and faded rather than removed, so the list does not
   collapse and re-expand under the pointer while the drop target is being chosen. */
.bookmarks li.dragging {
    opacity: .4;
    background: color-mix(in srgb, var(--accent) 8%, transparent);
}

/* Shown while the row is awaiting confirmation of its own deletion. */
.bookmarks li.confirming { background: color-mix(in srgb, var(--bad) 8%, transparent); }
.bookmarks li.confirming .bookmark-name { color: var(--bad); }

.bookmarks-empty { margin: 14px 0 0; font-size: 13px; color: var(--ink-soft); }
