/* =============================================================================
   DEX Portal - Home dashboard

   Cards are positioned absolutely by the page (see dashboard-page.js for why),
   so this sheet owns everything except left/top/width/height. Corner radius is
   set inline per card because each one can be given its own - 3px is the
   default and the rest of the sheet is built to look right at that.
   ============================================================================= */

/* The dashboard's own background - a hair of blue rather than the grey canvas
   or flat white. The cards stay white, so this is what separates them now.
   Hard-coded rather than tokenised because it belongs to this page only; if a
   second screen ever wants it, it becomes a variable then. */
.dash-surface {
    background: #f8fdff;
}

/* The greeting needs room around it. `.page-scroll` brings 18px of its own,
   and on a white page with no colour change to mark the join, that was not
   enough to stop the first row of cards crowding the name. */
.dash-scroll {
    padding-top: 26px;
}


/* ---------------------------------------------------------------- greeting */

.dash-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    padding: 24px var(--gutter) 20px;
    background: transparent;
}

.dash-header__greeting {
    margin: 0;
    font-size: 23px;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--text-primary);
}

.dash-header__day {
    margin: 3px 0 0;
    font-size: var(--font-size-base);
    color: var(--text-muted);
}

.dash-header__actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

.dash-round-button {
    width: 38px;
    height: 38px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: var(--surface-panel);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background var(--duration-instant) var(--easing-standard),
                color var(--duration-instant) var(--easing-standard),
                border-color var(--duration-instant) var(--easing-standard),
                transform var(--duration-instant) var(--easing-standard);
}

.dash-round-button:hover {
    background: var(--surface-subtle);
    color: var(--text-primary);
    transform: translateY(-1px);
}

.dash-round-button:active { transform: translateY(0); }

.dash-round-button--gear .icon {
    transition: transform var(--duration-panel-open) var(--easing-standard);
}

.dash-round-button--gear:hover .icon { transform: rotate(60deg); }

.is-editing .dash-round-button--gear {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--text-on-dark);
}




/* ------------------------------------------------------------- arrange bar */

.dash-editbar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 var(--gutter);
    max-height: 0;
    opacity: 0;
    overflow: hidden;
    background: var(--accent-tint);
    border-bottom: 1px solid var(--accent-border);
    transition: max-height var(--duration-quick) var(--easing-standard),
                opacity var(--duration-quick) var(--easing-standard),
                padding var(--duration-quick) var(--easing-standard);
}

.dash-editbar.is-open {
    max-height: 60px;
    opacity: 1;
    padding: 10px var(--gutter);
}

.dash-editbar__hint {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-right: auto;
    font-size: var(--font-size-small);
    color: var(--text-secondary);
}

.dash-editbar__hint .icon { color: var(--accent); flex-shrink: 0; }


/* -------------------------------------------------------------------- grid */

.dash-grid {
    position: relative;
    width: 100%;
    min-height: 120px;
    transition: height var(--duration-quick) var(--easing-standard);
}

.dash-card {
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--surface-panel);
    border: 1px solid var(--border-default);
    /* The fallback only. A card's own radius is written inline from its
       settings, and 5px is what a new one starts at. */
    border-radius: 5px;
    box-shadow: var(--shadow-card);
    will-change: transform;
    transition: transform 220ms var(--easing-standard),
                width 220ms var(--easing-standard),
                height 220ms var(--easing-standard),
                box-shadow var(--duration-instant) var(--easing-standard),
                border-color var(--duration-instant) var(--easing-standard),
                opacity 180ms var(--easing-standard);
}

.dash-card:hover {
    border-color: var(--border-strong);
    box-shadow: 0 6px 18px -10px rgba(16, 24, 40, 0.28);
}

/* The accent shows as a hairline down the leading edge - enough to group cards
   by eye without turning the dashboard into a colour chart. */
.dash-card[data-tone='accent'] { box-shadow: inset 3px 0 0 var(--accent), var(--shadow-card); }
.dash-card[data-tone='success'] { box-shadow: inset 3px 0 0 var(--status-success), var(--shadow-card); }
.dash-card[data-tone='danger'] { box-shadow: inset 3px 0 0 var(--status-danger), var(--shadow-card); }
.dash-card[data-tone='warning'] { box-shadow: inset 3px 0 0 var(--status-warning), var(--shadow-card); }
.dash-card[data-tone='info'] { box-shadow: inset 3px 0 0 var(--status-info), var(--shadow-card); }

.dash-card.is-arriving {
    opacity: 0;
    animation: dash-arrive 320ms var(--easing-standard) forwards;
    animation-delay: var(--arrive-delay, 0ms);
}

/* Opacity only. The card's transform is its POSITION - animating it here would
   fight the layout and land every card in the wrong place. */
@keyframes dash-arrive {
    from { opacity: 0; }
    to { opacity: 1; }
}

.dash-card.is-leaving { opacity: 0; }

.dash-card.is-dragging,
.dash-card.is-resizing {
    z-index: 5;
    transition: none;
    box-shadow: 0 22px 48px -18px rgba(16, 24, 40, 0.45);
    border-color: var(--accent);
    cursor: grabbing;
}

.dash-grid.is-arranging .dash-card:not(.is-dragging):not(.is-resizing) {
    border-style: dashed;
}


/* ------------------------------------------------------------- card chrome */

/* Card padding is set in one place: 18px down each side, a little more above
   the heading than below it so the title does not sit on the top edge. Rows add
   their own 8px inside that, which is why they look inset rather than ruled to
   the card wall. */
.dash-card__head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 15px 18px 9px;
    flex-shrink: 0;
}

.dash-card--bare .dash-card__head { display: none; }

.dash-card__title {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    margin-right: auto;
    padding: 0;
    border: 0;
    background: none;
    text-align: left;
    cursor: pointer;
    color: var(--text-primary);
}

.dash-card__icon { color: var(--text-muted); flex-shrink: 0; }

.dash-card__title:hover .dash-card__icon { color: var(--accent); }

.dash-card__title-text { display: flex; flex-direction: column; min-width: 0; }

.dash-card__name {
    font-size: var(--font-size-base);
    font-weight: 650;
    letter-spacing: -0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-card__title:hover .dash-card__name { color: var(--accent); }

/* Cards carry a heading and nothing under it. What a widget is filtered to
   lives in the title's tooltip - see applyTitleTooltip in dashboard-page.js. */

/* Nothing to press unless you are arranging. Hidden outright rather than faded,
   so a card being read carries no controls at all. */
.dash-card__actions {
    display: none;
    align-items: center;
    gap: 2px;
}

.is-editing .dash-card__actions { display: flex; }

.dash-icon-button {
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--radius-button);
    background: none;
    color: var(--text-muted);
    cursor: pointer;
    transition: background var(--duration-instant) var(--easing-standard),
                color var(--duration-instant) var(--easing-standard);
}

.dash-icon-button:hover { background: var(--surface-subtle); color: var(--text-primary); }
.dash-icon-button--danger:hover { background: var(--status-danger-tint); color: var(--status-danger); }

.dash-card__grip {
    display: none;
    align-items: center;
    color: var(--text-muted);
    cursor: grab;
    padding: 2px;
}

.dash-card__grip:active { cursor: grabbing; }

.dash-card__body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 0 18px 16px;
}

.dash-card--bare .dash-card__body { padding-top: 16px; }

.dash-card__resize {
    display: none;
    position: absolute;
    right: 0;
    bottom: 0;
    width: 18px;
    height: 18px;
    cursor: nwse-resize;
    touch-action: none;
}

.dash-card__resize::after {
    content: '';
    position: absolute;
    right: 4px;
    bottom: 4px;
    width: 7px;
    height: 7px;
    border-right: 2px solid var(--text-muted);
    border-bottom: 2px solid var(--text-muted);
    border-radius: 0 0 2px 0;
}

/* Handles exist only while arranging - a dashboard somebody is reading should
   not be covered in things to grab. */
.is-editing .dash-edit-only { display: flex; }
.is-editing .dash-card__actions { opacity: 1; }
.is-editing .dash-card__head { cursor: grab; touch-action: none; }


/* --------------------------------------------------------------- stat tile */

.dash-stat {
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 100%;
    height: 100%;
    padding: 2px 0;
    border: 0;
    background: none;
    text-align: left;
    cursor: pointer;
}

.dash-stat__value {
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -0.03em;
    color: var(--text-primary);
    line-height: 1.1;
}

.dash-stat--success .dash-stat__value { color: var(--status-success); }
.dash-stat--danger .dash-stat__value { color: var(--status-danger); }
.dash-stat--accent .dash-stat__value { color: var(--accent); }

.dash-stat__label {
    margin-top: 2px;
    font-size: var(--font-size-tiny);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
}

.dash-stat__foot {
    margin-top: 6px;
    font-size: var(--font-size-small);
    color: var(--text-secondary);
}

.dash-stat:hover .dash-stat__foot { color: var(--accent); }


/* --------------------------------------------------------- tabbed widget */
/* A widget that carries its own tabs (Domains, Email hosting): the bar stays
   put and the list under it scrolls, so switching state never loses your
   place in the card. */

.dash-tabbed {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.dash-tabs {
    display: flex;
    gap: 2px;
    flex: 0 0 auto;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--border-strong);
    overflow-x: auto;
}

.dash-tab {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 10px;
    border: 0;
    background: none;
    cursor: pointer;
    color: var(--text-muted);
    font-size: var(--font-size-small);
    font-weight: 600;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color var(--duration-instant) var(--easing-standard);
}

.dash-tab:hover { color: var(--text-primary); }

.dash-tab.is-active {
    color: var(--text-primary);
    border-bottom-color: var(--accent, #2f6bff);
}

.dash-tab__count {
    min-width: 20px;
    height: 18px;
    padding: 0 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--surface-subtle, #eef0f5);
    color: var(--text-secondary);
    font-size: var(--font-size-tiny);
    font-weight: 700;
}

.dash-tab__count--good { background: rgba(16, 185, 129, 0.15); color: #15803d; }
.dash-tab__count--warn { background: rgba(245, 158, 11, 0.18); color: #b45309; }
.dash-tab__count--bad  { background: rgba(239, 68, 68, 0.15); color: #b91c1c; }

.dash-tabbed__body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}


/* ------------------------------------------------------------------- rows */

.dash-rows { display: flex; flex-direction: column; }

.dash-row {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 8px;
    border: 0;
    /* The line between rows was --border-subtle (#f1f3f5), which on a white
       card is almost not there, and --border-default (#e8ebed) was barely
       better. A list needs its rows to read as separate things. */
    border-bottom: 1px solid var(--border-strong);
    background: none;
    text-align: left;
    cursor: pointer;
    border-radius: var(--radius-button);
    transition: background var(--duration-instant) var(--easing-standard);
}

.dash-row:last-child { border-bottom: 0; }

/* A day heading inside a list: "Tomorrow", and the events under it. */
.dash-rows__day {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 8px 6px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.dash-rows__day::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border-strong);
}

/* The heading provides the separation; the row above it does not need to. */
.dash-row:has(+ .dash-rows__day) { border-bottom: 0; }
.dash-row:hover { background: var(--surface-subtle); }

.dash-row__main { min-width: 0; margin-right: auto; }

/* Rows are read, not scanned for weight. The only bold thing on a card is its
   heading - everything a widget lists sits at normal weight, and colour does
   the emphasis where emphasis is wanted (a red end date, a red late tag). The
   stat tiles are the exception: their whole job is one large figure. */
.dash-row__name {
    font-size: var(--font-size-base);
    font-weight: 400;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-row__meta {
    font-size: var(--font-size-small);
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-row__end {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

.dash-row__value {
    font-size: var(--font-size-base);
    font-weight: 400;
    color: var(--text-primary);
}

.dash-row__value--danger { color: var(--status-danger); }

/* Same line, same size as the meta text it sits beside - only the colour
   changes, so it reads as part of the sentence rather than a badge. */
.dash-row__flag { font-weight: 400; }
.dash-row__flag--danger { color: var(--status-danger); }

/* Whose row it is. The faces overlap, so two people cost barely more width
   than one and the row stays a row. Each wears a ring in the card's own colour
   so the one in front reads as in front rather than as a smudge. */
.dash-row__faces {
    flex: none;
    display: inline-flex;
    align-items: center;
    margin-right: 10px;
}

.dash-face {
    flex: none;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    font-size: 9.5px;
    font-weight: 700;
    background: var(--accent-tint);
    color: var(--accent);
    box-shadow: 0 0 0 2px var(--surface-panel);
}

/* Every face after the first sits on the one before it. */
.dash-face + .dash-face {
    margin-left: -8px;
}

.dash-face--more {
    background: var(--surface-subtle);
    color: var(--text-muted);
    font-size: 9px;
}

.dash-row__go {
    color: var(--text-muted);
    opacity: 0;
    transform: translateX(-3px);
    transition: opacity var(--duration-instant) var(--easing-standard),
                transform var(--duration-instant) var(--easing-standard);
}

.dash-row:hover .dash-row__go { opacity: 1; transform: translateX(0); }

.dash-chip {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 7px;
    border-radius: var(--radius-button);
    font-size: var(--font-size-tiny);
    font-weight: 400;
    text-transform: capitalize;
    background: var(--status-neutral-tint);
    color: var(--status-neutral);
    white-space: nowrap;
}

/* A stage tag carries the stage's own colour, set inline. Its label is already
   written the way somebody typed it, so it is not re-cased here. */
.dash-chip--stage { text-transform: none; }

.dash-chip--good { background: var(--status-success-tint); color: var(--status-success); }
.dash-chip--bad { background: var(--status-danger-tint); color: var(--status-danger); }
.dash-chip--neutral { background: var(--status-neutral-tint); color: var(--status-neutral); }


/* ------------------------------------------------------------- bar chart */

.dash-bars { display: flex; flex-direction: column; gap: 2px; }

.dash-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 7px 6px;
    border: 0;
    background: none;
    text-align: left;
    cursor: pointer;
    border-radius: 3px;
    transition: background var(--duration-instant) var(--easing-standard);
}

.dash-bar:hover { background: var(--surface-subtle); }

.dash-bar__name {
    width: 38%;
    flex-shrink: 0;
    font-size: var(--font-size-small);
    color: var(--text-secondary);
    text-transform: capitalize;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-bar__track {
    flex: 1;
    height: 8px;
    border-radius: 3px;
    background: var(--surface-row-band);
    overflow: hidden;
}

.dash-bar__fill {
    display: block;
    height: 100%;
    min-width: 2px;
    border-radius: 3px;
    background: var(--accent);
    transition: width 420ms var(--easing-standard);
}

.dash-bar__count {
    width: 26px;
    text-align: right;
    font-size: var(--font-size-small);
    font-weight: 650;
    color: var(--text-primary);
}


/* --------------------------------------------------- empty, error, loading */

.dash-empty {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px 4px;
    font-size: var(--font-size-small);
    color: var(--text-muted);
}

.dash-empty .icon { color: var(--status-success); flex-shrink: 0; }
.dash-empty--bad { color: var(--status-danger); }
.dash-empty--bad .icon { color: var(--status-danger); }

/* Three sweeping bars where the content will land, rather than a spinner -
   the shape of the answer arrives before the answer does. */
.dash-loading {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 10px 2px;
}

.dash-loading::before,
.dash-loading::after {
    content: '';
    height: 10px;
    border-radius: 3px;
    background: linear-gradient(90deg,
        var(--surface-subtle) 25%, var(--surface-row-band) 37%, var(--surface-subtle) 63%);
    background-size: 400% 100%;
    animation: dash-sweep 1.3s ease-in-out infinite;
}

.dash-loading::after { width: 62%; }

@keyframes dash-sweep {
    from { background-position: 100% 50%; }
    to { background-position: 0 50%; }
}

.dash-blank {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 48px 24px;
    text-align: center;
    color: var(--text-muted);
}

.dash-blank .icon { color: var(--text-muted); margin-bottom: 6px; }
.dash-blank h3 { margin: 0; font-size: var(--font-size-medium); color: var(--text-primary); }
.dash-blank p { margin: 0; font-size: var(--font-size-base); max-width: 380px; }


/* ---------------------------------------------------- library and settings */

.dash-library__lead {
    margin: 0 0 16px;
    font-size: var(--font-size-base);
    color: var(--text-secondary);
}

.dash-library__group {
    margin: 16px 0 6px;
    font-size: var(--font-size-tiny);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-muted);
}

.dash-library__list { display: flex; flex-direction: column; gap: 6px; }

.dash-library__item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-button);
    background: var(--surface-panel);
    text-align: left;
    cursor: pointer;
    transition: border-color var(--duration-instant) var(--easing-standard),
                background var(--duration-instant) var(--easing-standard),
                transform var(--duration-instant) var(--easing-standard);
}

.dash-library__item:hover {
    border-color: var(--accent-border);
    background: var(--accent-tint);
    transform: translateX(2px);
}

.dash-library__glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: var(--radius-button);
    background: var(--surface-subtle);
    color: var(--text-secondary);
}

.dash-library__item:hover .dash-library__glyph { background: var(--surface-panel); color: var(--accent); }

.dash-library__text { display: flex; flex-direction: column; min-width: 0; margin-right: auto; }

.dash-library__name { font-size: var(--font-size-base); font-weight: 600; color: var(--text-primary); }
.dash-library__desc { font-size: var(--font-size-small); color: var(--text-muted); }

.dash-library__add { color: var(--text-muted); flex-shrink: 0; }
.dash-library__item:hover .dash-library__add { color: var(--accent); }

.dash-settings .form-section + .form-section { margin-top: 18px; }

.dash-settings__radius { display: flex; align-items: center; gap: 12px; }

.dash-settings__range { flex: 1; accent-color: var(--accent); }

.dash-settings__value {
    width: 46px;
    text-align: right;
    font-size: var(--font-size-small);
    font-variant-numeric: tabular-nums;
    color: var(--text-secondary);
}


/* ------------------------------------------------------------------ small */

/* ----------------------------------------------------------------- narrow

   Below the full grid the board is re-flowed into one or two columns and
   arranging is switched off - the page says so rather than showing a gear that
   would not do anything. */

.dash-surface.is-narrow .dash-round-button--gear { display: none; }
.dash-surface.is-narrow .dash-card__grip,
.dash-surface.is-narrow .dash-card__resize,
.dash-surface.is-narrow .dash-card__actions { display: none; }

@media (max-width: 900px) {
    .dash-header {
        padding: 16px var(--gutter-tight) 14px;
        gap: 10px;
    }

    .dash-header__greeting { font-size: 19px; }
    .dash-header__day { font-size: var(--font-size-small); }

    .dash-scroll { padding: 18px var(--gutter-tight) var(--gutter-tight); }

    .dash-editbar.is-open { padding: 10px var(--gutter-tight); }
    .dash-editbar__hint { display: none; }

    .dash-card__head { padding: 13px 14px 8px; }
    .dash-card__body { padding: 0 14px 13px; }

    /* A row on a phone is a thumb target, and the name matters more than the
       meta line under it. */
    .dash-row { padding: 11px 4px; gap: 8px; }
    .dash-row__go { display: none; }

    .dash-stat__value { font-size: 23px; }

    .dash-bar__name { width: 44%; }
}

@media (max-width: 620px) {
    .dash-header {
        flex-direction: column;
        align-items: flex-start;
    }

    .dash-header__actions { align-self: flex-end; margin-top: -34px; }

    .dash-scroll { padding: 14px 12px 20px; }

    .dash-row__value { font-size: var(--font-size-small); }
}

@media (prefers-reduced-motion: reduce) {
    .dash-card,
    .dash-grid,
    .dash-bar__fill,
    .dash-round-button { transition: none; }

    .dash-card.is-arriving { animation: none; opacity: 1; }
    .dash-loading::before,
    .dash-loading::after { animation: none; }
}
