/* ==========================================================================
   Pulse — Design System

   Shares the token set used by Energy Watch / Petrol Heatmap / Tube Tracker:
   deep navy base, translucent slate panels, a cyan→blue accent ramp, and the
   Outfit / Inter / JetBrains Mono type stack. Themes are driven by
   [data-theme] on <html>; every colour below resolves through a variable so a
   theme only has to restate the palette.
   ========================================================================== */

:root {
    /* Surfaces */
    --bg-base: #080c14;
    --bg-raised: #0f1729;
    --bg-card: rgba(15, 23, 42, 0.78);
    --bg-inset: rgba(255, 255, 255, 0.04);
    --bg-inset-strong: rgba(255, 255, 255, 0.08);
    --panel-border: rgba(255, 255, 255, 0.10);
    --panel-border-strong: rgba(255, 255, 255, 0.18);

    /* Ink */
    --text-main: #f8fafc;
    --text-muted: #94a3b8;
    --text-dim: #64748b;
    --on-accent: #04121c;

    /* Accents */
    --accent-blue: #00f2fe;
    --accent-cyan: #4facfe;
    --accent-gold: #ffb703;
    --accent-emerald: #10b981;
    --accent-rose: #ff5252;

    /* Session semantics */
    --color-focus: #00f2fe;
    --color-break: #10b981;
    --color-planning: #ffb703;
    --color-away: #64748b;

    --gradient-primary: linear-gradient(135deg, #00f2fe 0%, #4facfe 100%);
    --gradient-accent: linear-gradient(135deg, #4facfe 0%, #7209b7 100%);

    /* Type */
    --font-heading: 'Outfit', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

    /* Geometry */
    --radius-lg: 16px;
    --radius-md: 12px;
    --radius-sm: 8px;
    --radius-full: 9999px;

    --glass-shadow: 0 12px 36px 0 rgba(0, 0, 0, 0.45);
    --glass-glow: 0 0 20px rgba(0, 242, 254, 0.15);
    --glass-blur: blur(18px);

    --orb-1: #00f2fe;
    --orb-2: #7209b7;
    --orb-3: #10b981;
    --orb-opacity: 0.22;
    --select-option-bg: #0f1729;

    /* Chart marks are large filled areas, so they need a darker step of the
       accent hue than UI accents do — the bright cyan sits at L 0.87, well
       outside the 0.48–0.67 band a fill should occupy on this surface.
       Validated against the card surface for lightness, chroma and contrast. */
    --chart-bar: #0ea5b9;
    --chart-grid: rgba(255, 255, 255, 0.08);
}

[data-theme="light"] {
    --bg-base: #eef1f6;
    --bg-raised: #ffffff;
    --bg-card: rgba(255, 255, 255, 0.88);
    --bg-inset: rgba(15, 23, 42, 0.04);
    --bg-inset-strong: rgba(15, 23, 42, 0.08);
    --panel-border: rgba(15, 23, 42, 0.12);
    --panel-border-strong: rgba(15, 23, 42, 0.22);

    --text-main: #0f172a;
    --text-muted: #56617a;
    --text-dim: #8590a6;
    --on-accent: #ffffff;

    /* The dark-mode cyan sits at roughly 1.6:1 on a white card. These steps
       are the same hues carried down to a legible contrast on pale surfaces. */
    --accent-blue: #0284a8;
    --accent-cyan: #0b6fc4;
    --accent-gold: #a16207;
    --accent-emerald: #047857;
    --accent-rose: #be123c;

    --color-focus: #0284a8;
    --color-break: #047857;
    --color-planning: #a16207;
    --color-away: #64748b;

    --gradient-primary: linear-gradient(135deg, #0284a8 0%, #0b6fc4 100%);
    --gradient-accent: linear-gradient(135deg, #0b6fc4 0%, #6d28d9 100%);

    --glass-shadow: 0 12px 36px 0 rgba(15, 23, 42, 0.10);
    --glass-glow: 0 0 20px rgba(11, 111, 196, 0.10);

    --orb-opacity: 0.14;
    --select-option-bg: #ffffff;

    /* Its own validated step against the light surface, not a flipped value. */
    --chart-bar: #0284a8;
    --chart-grid: rgba(15, 23, 42, 0.10);
}

[data-theme="emerald"] {
    --bg-base: #041813;
    --bg-raised: #072a20;
    --bg-card: rgba(7, 42, 32, 0.78);
    --bg-inset: rgba(255, 255, 255, 0.04);
    --bg-inset-strong: rgba(255, 255, 255, 0.08);
    --panel-border: rgba(52, 211, 153, 0.18);
    --panel-border-strong: rgba(52, 211, 153, 0.34);

    --text-main: #e6fff5;
    --text-muted: #8fd3ba;
    --text-dim: #57917d;
    --on-accent: #04211a;

    --accent-blue: #34d399;
    --accent-cyan: #6ee7b7;
    --accent-gold: #fbbf24;
    --accent-emerald: #34d399;
    --accent-rose: #fb7185;

    --color-focus: #34d399;
    --color-break: #6ee7b7;
    --color-planning: #fbbf24;
    --color-away: #57917d;

    --gradient-primary: linear-gradient(135deg, #34d399 0%, #059669 100%);
    --gradient-accent: linear-gradient(135deg, #6ee7b7 0%, #0d9488 100%);

    --glass-shadow: 0 12px 36px 0 rgba(0, 0, 0, 0.5);
    --glass-glow: 0 0 20px rgba(52, 211, 153, 0.18);

    --orb-1: #34d399;
    --orb-2: #0d9488;
    --orb-3: #a3e635;
    --select-option-bg: #072a20;

    --chart-bar: #0f9d76;
    --chart-grid: rgba(255, 255, 255, 0.08);
}

/* --------------------------------------------------------------- base */

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* The room changes colour with the session.
 *
 * Kept to a wash rather than a colour change: the panels, the charts and the
 * status badges all carry meaning through colour, and a strong background would
 * shift how every one of them reads. This is peripheral — enough to notice
 * without looking, which is the point when the tab is behind something else.
 *
 * Defaults to the base colour so the mix is a no-op when nothing is running. */
:root { --session-wash: var(--bg-base); }

html[data-session="focus"] { --session-wash: var(--color-focus); }
html[data-session="break"] { --session-wash: var(--color-break); }
/* Paused keeps the mode's hue but drains it, so a suspended session looks
   suspended rather than active. */
html[data-session="paused"] { --session-wash: var(--color-away); }

body {
    font-family: var(--font-body);
    background-color: color-mix(in srgb, var(--bg-base) 92%, var(--session-wash));
    /* Slow on purpose: a snap to a new colour is startling mid-sentence. */
    transition: background-color 1.6s ease;
    color: var(--text-main);
    min-height: 100vh;
    overflow-x: hidden;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    background: var(--panel-border-strong);
    border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--accent-blue);
}

select option {
    background-color: var(--select-option-bg);
    color: var(--text-main);
}

.hidden {
    display: none !important;
}

/* Present to assistive technology, absent visually. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* A visible focus ring everywhere. :focus-visible rather than :focus so mouse
   users never see it, which is what let it be omitted in the first place. */
:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

.app-background {
    position: fixed;
    inset: 0;
    z-index: -1;
    overflow: hidden;
}

.glow-orb {
    position: absolute;
    border-radius: 50%;
    filter: blur(120px);
    opacity: var(--orb-opacity);
    pointer-events: none;
}

.glow-orb { transition: background 1.6s ease, opacity 1.6s ease; }

html[data-session="focus"] .orb-1,
html[data-session="focus"] .orb-3 { background: var(--color-focus); }
html[data-session="break"] .orb-1,
html[data-session="break"] .orb-3 { background: var(--color-break); }
html[data-session="paused"] .glow-orb { opacity: calc(var(--orb-opacity) * 0.5); }

.orb-1 { width: 500px; height: 500px; background: var(--orb-1); top: -140px; left: -120px; }
.orb-2 { width: 600px; height: 600px; background: var(--orb-2); bottom: -180px; right: -120px; }
.orb-3 { width: 400px; height: 400px; background: var(--orb-3); top: 45%; left: 42%; }

.glass-panel {
    background: var(--bg-card);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--panel-border);
    box-shadow: var(--glass-shadow);
    border-radius: var(--radius-lg);
}

/* ------------------------------------------------------------- modal */

.modal-overlay {
    position: fixed;
    inset: 0;
    background: color-mix(in srgb, var(--bg-base) 88%, transparent);
    backdrop-filter: blur(12px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 20px;
    overflow-y: auto;
}

.modal-card {
    position: relative;
    width: 100%;
    max-width: 540px;
    padding: 36px;
    text-align: center;
}

.modal-close {
    position: absolute;
    top: 14px;
    right: 18px;
    background: transparent;
    border: none;
    color: var(--text-dim);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: var(--radius-sm);
}

.modal-close:hover {
    color: var(--text-main);
    background: var(--bg-inset);
}

.modal-tabs {
    display: flex;
    gap: 8px;
    margin-bottom: 24px;
    border-bottom: 1px solid var(--panel-border);
    padding-bottom: 12px;
}

.modal-tab {
    flex: 1;
    padding: 10px 14px;
    font-family: var(--font-body);
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-muted);
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    transition: color 0.2s ease, border-color 0.2s ease;
}

.modal-tab.active {
    color: var(--accent-blue);
    border-bottom-color: var(--accent-blue);
}

.modal-header h2 {
    font-family: var(--font-heading);
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: -0.5px;
    margin: 12px 0 8px;
}

.modal-header p {
    color: var(--text-muted);
    font-size: 0.95rem;
    margin-bottom: 24px;
}

.logo-icon-large {
    font-size: 3rem;
    display: inline-block;
}

/* ------------------------------------------------------------- admin */

.admin-section {
    text-align: left;
    padding: 16px 0;
}

.admin-section.border-bottom {
    border-bottom: 1px solid var(--panel-border);
}

.admin-section h3 {
    font-family: var(--font-heading);
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: 12px;
}

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

.admin-form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 8px;
}

.admin-form-row input {
    flex: 1 1 160px;
    min-width: 0;
    padding: 10px 14px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-md);
    color: var(--text-main);
    font-family: var(--font-body);
    font-size: 0.9rem;
    outline: none;
}

.admin-form-row input:focus {
    border-color: var(--accent-blue);
    box-shadow: var(--glass-glow);
}

.reset-layout {
    display: block;
    margin: 14px auto 0;
    color: var(--text-dim);
}

.admin-hint {
    margin-top: 12px;
    text-align: left;
    font-size: 0.8rem;
    color: var(--text-dim);
}

.admin-hint code {
    font-family: var(--font-mono);
    font-size: 0.76rem;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-sm);
    padding: 1px 6px;
    color: var(--text-muted);
}

.admin-roster-box {
    margin-bottom: 14px;
}

.admin-roster-box label {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.roster-chips-container {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
    max-height: 130px;
    overflow-y: auto;
    padding: 10px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-sm);
}

.roster-empty {
    color: var(--text-dim);
    font-size: 0.85rem;
}

.member-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: color-mix(in srgb, var(--accent-blue) 14%, transparent);
    color: var(--accent-blue);
    padding: 4px 10px;
    border-radius: var(--radius-full);
    font-size: 0.82rem;
    font-weight: 600;
    border: 1px solid color-mix(in srgb, var(--accent-blue) 32%, transparent);
}

.btn-chip-remove {
    background: transparent;
    border: none;
    color: var(--accent-rose);
    cursor: pointer;
    font-weight: 700;
    font-size: 1rem;
    line-height: 1;
    padding: 0 2px;
}

.btn-danger-sm {
    background: color-mix(in srgb, var(--accent-rose) 16%, transparent);
    color: var(--accent-rose);
    border: 1px solid color-mix(in srgb, var(--accent-rose) 40%, transparent);
    padding: 5px 12px;
    font-family: var(--font-body);
    font-size: 0.78rem;
    font-weight: 600;
    border-radius: var(--radius-sm);
    cursor: pointer;
    white-space: nowrap;
}

.btn-danger-sm:hover {
    background: color-mix(in srgb, var(--accent-rose) 30%, transparent);
}

.input-group {
    text-align: left;
    margin-bottom: 20px;
}

.input-group label {
    display: block;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 8px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.input-group input,
.input-group select {
    width: 100%;
    padding: 13px 16px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-md);
    color: var(--text-main);
    font-family: var(--font-body);
    font-size: 1rem;
    outline: none;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.input-group input:focus,
.input-group select:focus {
    border-color: var(--accent-blue);
    box-shadow: var(--glass-glow);
}

/* --------------------------------------------------------- app shell */

.app-container {
    max-width: 1380px;
    margin: 0 auto;
    padding: 16px;
}

.top-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    padding: 12px 20px;
    margin-bottom: 14px;
}

.brand {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 4px 8px;
    margin: -4px -8px;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: background 0.15s ease;
}

.brand:hover {
    background: var(--bg-inset);
}

.brand:hover .logo-icon {
    transform: scale(1.08);
}

.logo-icon {
    font-size: 1.7rem;
    transition: transform 0.15s ease;
}

.brand-text h1 {
    font-family: var(--font-heading);
    font-size: 1.35rem;
    font-weight: 800;
    letter-spacing: -0.5px;
    line-height: 1.1;
}

/* The deploy stamp, sitting quietly under the wordmark. */
.app-version {
    display: block;
    margin-top: 3px;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.3px;
    color: var(--text-dim);
    cursor: default;
}

/* The header's copy is hidden behind this modal while it is open, so this is
   the only place a first-time visitor ever sees the build in use. Shared by
   both tabs, sitting quietly below whichever one is open. */
.login-version {
    margin: 16px 0 0;
    padding-top: 12px;
    border-top: 1px solid var(--panel-border);
    text-align: center;
}


.room-selector-wrapper {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--bg-inset);
    padding: 6px 8px 6px 16px;
    border-radius: var(--radius-full);
    border: 1px solid var(--panel-border);
}

.room-selector-wrapper .label {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-dim);
}

.room-selector-wrapper select {
    background: transparent;
    border: none;
    color: var(--text-main);
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 0.92rem;
    outline: none;
    cursor: pointer;
    max-width: 200px;
}

.user-profile-pill {
    display: flex;
    align-items: center;
    gap: 12px;
    background: var(--bg-inset);
    padding: 6px 16px 6px 6px;
    border-radius: var(--radius-full);
    border: 1px solid var(--panel-border);
}

.user-avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--gradient-accent);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.9rem;
}

.user-info {
    display: flex;
    align-items: center;
    gap: 8px;
}

.nav-name {
    font-weight: 600;
    font-size: 0.9rem;
}

.connection-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--color-break);
    box-shadow: 0 0 10px var(--color-break);
    transition: background 0.3s ease;
}

.connection-dot.offline {
    background: var(--accent-rose);
    box-shadow: 0 0 10px var(--accent-rose);
    animation: pulse 1.4s infinite;
}

/* ------------------------------------------------------------ layout */

/* Every panel is a direct child of this grid, which is what makes them
   reorderable as a single list. The gap is the only thing separating them —
   cards carry no bottom margin, or the two would stack up. */
.workspace-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
    align-items: start;
}

/* Panels that need the full width keep it wherever they are moved to. */
.timer-card,
.kanban-card {
    grid-column: 1 / -1;
}

@media (max-width: 1080px) {
    .workspace-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.card {
    padding: 20px;
    margin-bottom: 0;
}

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

.card-header.border-bottom {
    padding-bottom: 12px;
    border-bottom: 1px solid var(--panel-border);
}

/* ------------------------------------------------- collapsible panels */

/* Grip and chevron sit together at the header's right edge; the grip claims the
   spare space so both stay put regardless of what else the header holds. */
.panel-grip {
    flex: 0 0 auto;
    margin-left: auto;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-dim);
    font-size: 0.9rem;
    line-height: 1;
    cursor: grab;
    transition: background 0.15s ease, color 0.15s ease;
}

.panel-grip:hover {
    background: var(--bg-inset);
    border-color: var(--panel-border);
    color: var(--text-main);
}

.panel-grip:active {
    cursor: grabbing;
}

.panel-grip + .panel-toggle {
    margin-left: 0;
}

.card.panel-dragging {
    opacity: 0.45;
    border-color: var(--accent-blue);
}

.panel-toggle {
    flex: 0 0 auto;
    margin-left: auto;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--panel-border);
    background: var(--bg-inset);
    color: var(--text-muted);
    font-size: 0.8rem;
    line-height: 1;
    cursor: pointer;
    transition: transform 0.2s ease, background 0.15s ease, color 0.15s ease;
}

.panel-toggle:hover {
    background: var(--bg-inset-strong);
    color: var(--text-main);
}

/* The chevron is the state indicator, so it must survive reduced-motion —
   this is a transform, not an animation, and stays instant rather than absent. */
.card.collapsed .panel-toggle {
    transform: rotate(-90deg);
}

/* Everything except the header is hidden. Collapsing by display rather than
   height keeps the grid from reserving space for a panel that is not there. */
.card.collapsed > *:not(.card-header) {
    display: none;
}

.card.collapsed {
    padding-bottom: 18px;
}

/* A collapsed panel's header rule would be a line under nothing. */
.card.collapsed .card-header {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

.card:not(.collapsed) > *:not(.card-header) {
    animation: panelReveal 0.22s ease-out;
}

@keyframes panelReveal {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: none; }
}

.card-header h2 {
    font-family: var(--font-heading);
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -0.3px;
}

.subtitle {
    font-size: 0.82rem;
    color: var(--text-muted);
    margin-top: 2px;
}

.header-actions {
    display: flex;
    gap: 8px;
}

/* ------------------------------------------------------------- timer */

.mode-pill {
    font-size: 0.78rem;
    font-weight: 600;
    padding: 4px 12px;
    border-radius: var(--radius-full);
    border: 1px solid transparent;
}

.mode-pill.mode-focus {
    background: color-mix(in srgb, var(--color-focus) 14%, transparent);
    color: var(--color-focus);
    border-color: color-mix(in srgb, var(--color-focus) 32%, transparent);
}

.mode-pill.mode-break {
    background: color-mix(in srgb, var(--color-break) 14%, transparent);
    color: var(--color-break);
    border-color: color-mix(in srgb, var(--color-break) 32%, transparent);
}

/* The timer spans the whole grid so the ring, the session settings and the
   task context can sit as three columns rather than one tall stack. */
.timer-card {
    grid-column: 1 / -1;
}

.timer-layout {
    display: grid;
    grid-template-columns: auto minmax(230px, 1fr) minmax(280px, 1.3fr);
    gap: 28px;
    align-items: start;
}

.timer-visual {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
}

.timer-config,
.timer-context {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* The controls columns are shorter than the ring; centring them stops the card
   looking top-heavy on the right. */
.timer-config {
    justify-content: center;
    min-height: 240px;
}

.timer-context {
    justify-content: center;
    min-height: 240px;
}

.timer-context .group-sprint-banner {
    margin-top: 6px;
}

@media (max-width: 1180px) {
    .timer-layout {
        grid-template-columns: auto minmax(0, 1fr);
    }
    .timer-context {
        grid-column: 1 / -1;
        min-height: 0;
    }
}

@media (max-width: 780px) {
    .timer-layout {
        grid-template-columns: minmax(0, 1fr);
    }
    .timer-config,
    .timer-context {
        min-height: 0;
    }
}

.timer-display-container {
    position: relative;
    width: 240px;
    height: 240px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.progress-ring {
    transform: rotate(-90deg);
}

.progress-ring__circle-bg {
    stroke: var(--bg-inset-strong);
}

.progress-ring__circle {
    transition: stroke-dashoffset 0.5s ease-in-out;
    filter: drop-shadow(0 0 8px color-mix(in srgb, var(--accent-blue) 45%, transparent));
}

.timer-time-wrapper {
    position: absolute;
    text-align: center;
    padding: 0 40px;
}

.timer-clock {
    font-family: var(--font-heading);
    font-size: 3.4rem;
    font-weight: 800;
    letter-spacing: -1px;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.timer-subtext {
    font-size: 0.82rem;
    color: var(--text-muted);
    margin-top: 8px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ------------------------------------------------- session length controls */

.duration-controls {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    margin-bottom: 14px;
}

.duration-field label {
    display: block;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.duration-input {
    display: flex;
    align-items: center;
    gap: 2px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-md);
    padding: 4px 10px 4px 4px;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.duration-input:focus-within {
    border-color: var(--accent-blue);
    box-shadow: var(--glass-glow);
}

.duration-input input {
    flex: 1;
    min-width: 0;
    width: 100%;
    background: transparent;
    border: none;
    outline: none;
    color: var(--text-main);
    font-family: var(--font-mono);
    font-size: 1.05rem;
    font-weight: 700;
    text-align: center;
    padding: 4px 0;
    font-variant-numeric: tabular-nums;
}

/* The − / + steppers replace these, and the native arrows are tiny and ugly. */
.duration-input input::-webkit-outer-spin-button,
.duration-input input::-webkit-inner-spin-button {
    appearance: none;
    margin: 0;
}

.duration-input input[type='number'] {
    -moz-appearance: textfield;
    appearance: textfield;
}

.btn-step {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--panel-border);
    background: var(--bg-inset-strong);
    color: var(--text-muted);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    transition: all 0.15s ease;
}

.btn-step:hover {
    background: color-mix(in srgb, var(--accent-blue) 20%, transparent);
    border-color: color-mix(in srgb, var(--accent-blue) 40%, transparent);
    color: var(--accent-blue);
}

.duration-unit {
    flex: 0 0 auto;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-dim);
    text-transform: uppercase;
}

.mode-toggle {
    display: flex;
    gap: 6px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-md);
    padding: 4px;
    margin-bottom: 20px;
}

.btn-mode {
    flex: 1;
    padding: 9px 4px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-family: var(--font-body);
    font-size: 0.86rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
}

.btn-mode:hover {
    color: var(--text-main);
}

.btn-mode.active {
    background: color-mix(in srgb, var(--accent-blue) 18%, transparent);
    color: var(--accent-blue);
    border-color: color-mix(in srgb, var(--accent-blue) 40%, transparent);
}

.task-input-wrapper {
    margin-bottom: 18px;
}

.task-input-wrapper label {
    display: block;
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.task-input-box input {
    width: 100%;
    padding: 12px 16px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-md);
    color: var(--text-main);
    font-family: var(--font-body);
    font-size: 0.93rem;
    outline: none;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.task-input-box input:focus {
    border-color: var(--accent-blue);
    box-shadow: var(--glass-glow);
}

/* ----------------------------------------------------------- buttons */

.btn {
    padding: 12px 22px;
    border-radius: var(--radius-md);
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 0.93rem;
    cursor: pointer;
    border: 1px solid transparent;
    transition: all 0.2s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    white-space: nowrap;
}

.btn-primary {
    background: var(--gradient-primary);
    color: var(--on-accent);
    font-weight: 700;
}

.btn-secondary {
    background: var(--bg-inset-strong);
    color: var(--text-main);
    border-color: var(--panel-border);
}

.btn-secondary:hover {
    border-color: var(--panel-border-strong);
}

.btn-ghost {
    background: transparent;
    color: var(--text-muted);
}

.btn-ghost:hover {
    color: var(--text-main);
    background: var(--bg-inset);
}

.btn-accent {
    background: var(--gradient-accent);
    color: #fff;
}

.btn-glow:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 25px color-mix(in srgb, var(--accent-blue) 35%, transparent);
}

.btn-large {
    width: 100%;
    padding: 15px;
    font-size: 1.02rem;
}

.btn-sm {
    padding: 8px 14px;
    font-size: 0.83rem;
}

.interruption-cost {
    align-self: center;
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--accent-gold);
    font-variant-numeric: tabular-nums;
    margin-bottom: 4px;
}

.command-row.status-paused { border-left-color: var(--accent-cyan); }

/* Board rows carry no status of their own — they describe work, not a person. */
.command-task-row {
    grid-template-columns: minmax(0, 3fr) auto auto;
    border-left-color: var(--panel-border-strong);
}

/* An editable estimate still has to read as the badge it replaced. */
.estimate-select {
    border: 1px solid color-mix(in srgb, var(--accent-gold) 30%, transparent);
    cursor: pointer;
    appearance: none;
    padding-right: 8px;
}

.estimate-select:focus {
    outline: 2px solid var(--accent-blue);
    outline-offset: 1px;
}

.kanban-task-title[role="button"] {
    cursor: text;
    border-radius: var(--radius-sm);
}

.kanban-task-title[role="button"]:hover {
    background: var(--bg-inset-strong);
}

.kanban-rename-input {
    width: 100%;
    background: var(--bg-inset-strong);
    border: 1px solid var(--accent-blue);
    border-radius: var(--radius-sm);
    color: var(--text-main);
    font-family: var(--font-body);
    font-size: 0.92rem;
    font-weight: 600;
    padding: 2px 6px;
    outline: none;
}

.timer-actions {
    display: flex;
    gap: 10px;
    width: 100%;
    max-width: 280px;
}

.timer-actions .btn-primary,
.timer-actions .btn-secondary {
    flex: 2;
}

.timer-actions .btn-ghost {
    flex: 1;
}

.timer-settings-row {
    margin: 14px 0 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
}

.tick-volume {
    width: 84px;
    vertical-align: middle;
}

.tick-sound-select {
    padding: 7px 10px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-sm);
    color: var(--text-main);
    font-family: var(--font-body);
    font-size: 0.83rem;
    outline: none;
    cursor: pointer;
    max-width: 190px;
}

.tick-sound-select:focus {
    border-color: var(--accent-blue);
}

/* A pressed-in look for the tick toggle, so its state reads without sound. */
.timer-settings-row .btn.active {
    background: color-mix(in srgb, var(--accent-blue) 18%, transparent);
    border-color: color-mix(in srgb, var(--accent-blue) 40%, transparent);
    color: var(--accent-blue);
}

.group-sprint-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    padding: 14px 18px;
    background: color-mix(in srgb, var(--accent-cyan) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent-cyan) 22%, transparent);
    border-radius: var(--radius-md);
}

.sprint-info {
    display: flex;
    align-items: center;
    gap: 12px;
}

.sprint-icon {
    font-size: 1.4rem;
}

.sprint-info strong {
    font-size: 0.9rem;
    display: block;
}

.sprint-info p {
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* ------------------------------------------------------------- audio */

.ambient-tracks {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.track-row {
    display: flex;
    align-items: center;
    gap: 16px;
    background: var(--bg-inset);
    padding: 10px 16px;
    border-radius: var(--radius-md);
    border: 1px solid var(--panel-border);
    transition: background 0.2s ease, border-color 0.2s ease;
}

.track-info {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1;
    min-width: 0;
    font-size: 0.88rem;
    font-weight: 600;
}

.track-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.track-hint {
    font-size: 0.68rem;
    font-weight: 500;
    color: var(--text-dim);
    white-space: nowrap;
}

/* Says which source a playing track is using, so a dropped-in file that was
   never picked up is obvious rather than silently ignored. */
.track-row[data-source] .track-info::after {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    padding: 1px 6px;
    border-radius: var(--radius-full);
    border: 1px solid transparent;
    flex: 0 0 auto;
}

.track-row[data-source="sample"] .track-info::after {
    content: 'sample';
    background: color-mix(in srgb, var(--accent-emerald) 14%, transparent);
    border-color: color-mix(in srgb, var(--accent-emerald) 30%, transparent);
    color: var(--accent-emerald);
}

.track-row[data-source="synth"] .track-info::after {
    content: 'synth';
    background: var(--bg-inset-strong);
    border-color: var(--panel-border);
    color: var(--text-dim);
}

.track-controls {
    display: flex;
    align-items: center;
    gap: 12px;
}

.volume-slider {
    width: 92px;
    accent-color: var(--accent-blue);
}

.btn-play-toggle {
    background: color-mix(in srgb, var(--accent-blue) 14%, transparent);
    color: var(--accent-blue);
    border: 1px solid color-mix(in srgb, var(--accent-blue) 30%, transparent);
    padding: 5px 12px;
    font-family: var(--font-body);
    font-size: 0.78rem;
    font-weight: 700;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: all 0.15s ease;
    min-width: 70px;
}

.btn-play-toggle:hover {
    background: color-mix(in srgb, var(--accent-blue) 28%, transparent);
}

.btn-play-toggle.playing {
    background: color-mix(in srgb, var(--accent-rose) 18%, transparent);
    color: var(--accent-rose);
    border-color: color-mix(in srgb, var(--accent-rose) 40%, transparent);
}

.track-row.active {
    background: color-mix(in srgb, var(--accent-blue) 10%, transparent);
    border-color: color-mix(in srgb, var(--accent-blue) 30%, transparent);
}

/* ------------------------------------------------------- team matrix */

.team-stats {
    display: flex;
    gap: 22px;
}

.stat-box {
    text-align: right;
}

.stat-value {
    display: block;
    font-family: var(--font-heading);
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--accent-blue);
    font-variant-numeric: tabular-nums;
}

.stat-label {
    font-size: 0.72rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
}

.status-filters {
    display: flex;
    gap: 8px;
    margin-bottom: 18px;
    overflow-x: auto;
    padding-bottom: 2px;
}

.filter-tab {
    padding: 7px 14px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-full);
    color: var(--text-muted);
    font-family: var(--font-body);
    font-size: 0.83rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
    white-space: nowrap;
}

.filter-tab.active {
    background: var(--bg-inset-strong);
    color: var(--text-main);
    border-color: var(--panel-border-strong);
}

.team-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 14px;
    max-height: 520px;
    overflow-y: auto;
    padding-right: 4px;
}

.empty-state {
    grid-column: 1 / -1;
    text-align: center;
    color: var(--text-muted);
    padding: 36px 0;
    font-size: 0.88rem;
}

.spinner {
    width: 26px;
    height: 26px;
    margin: 0 auto 12px;
    border: 2px solid var(--panel-border);
    border-top-color: var(--accent-blue);
    border-radius: 50%;
    animation: spin 0.9s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

.team-card-item {
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-left: 4px solid var(--color-away);
    border-radius: var(--radius-md);
    padding: 15px;
    transition: transform 0.2s ease, border-color 0.2s ease;
}

.team-card-item:hover {
    transform: translateY(-2px);
    border-color: var(--panel-border-strong);
}

.team-card-item.status-focus { border-left-color: var(--color-focus); }
.team-card-item.status-break { border-left-color: var(--color-break); }
.team-card-item.status-planning { border-left-color: var(--color-planning); }
.team-card-item.status-away { border-left-color: var(--color-away); opacity: 0.72; }

.user-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 10px;
}

.user-name-wrapper {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.member-avatar {
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--bg-inset-strong);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.85rem;
}

.member-name {
    font-weight: 600;
    font-size: 0.92rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.status-badge {
    flex: 0 0 auto;
    font-size: 0.72rem;
    font-weight: 600;
    padding: 3px 9px;
    border-radius: var(--radius-full);
    border: 1px solid transparent;
    white-space: nowrap;
}

.badge-focus {
    background: color-mix(in srgb, var(--color-focus) 14%, transparent);
    color: var(--color-focus);
    border-color: color-mix(in srgb, var(--color-focus) 32%, transparent);
}

.badge-break {
    background: color-mix(in srgb, var(--color-break) 14%, transparent);
    color: var(--color-break);
    border-color: color-mix(in srgb, var(--color-break) 32%, transparent);
}

.badge-planning {
    background: color-mix(in srgb, var(--color-planning) 14%, transparent);
    color: var(--color-planning);
    border-color: color-mix(in srgb, var(--color-planning) 32%, transparent);
}

.badge-paused {
    background: color-mix(in srgb, var(--accent-cyan) 14%, transparent);
    color: var(--accent-cyan);
    border-color: color-mix(in srgb, var(--accent-cyan) 32%, transparent);
}

.badge-away {
    background: var(--bg-inset-strong);
    color: var(--text-muted);
    border-color: var(--panel-border);
}

.user-task-text,
.user-status-note {
    font-size: 0.83rem;
    color: var(--text-muted);
    margin-bottom: 8px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.user-status-note {
    color: var(--accent-gold);
}

.user-timer-counter {
    font-family: var(--font-mono);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-main);
    margin-bottom: 8px;
    font-variant-numeric: tabular-nums;
}

.user-stats-line {
    font-size: 0.75rem;
    color: var(--text-dim);
    margin-bottom: 10px;
}

.kudos-bar {
    display: flex;
    gap: 6px;
}

.btn-kudos {
    flex: 1;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-sm);
    padding: 6px 0;
    font-size: 0.9rem;
    cursor: pointer;
    transition: transform 0.15s ease, background 0.15s ease;
}

.btn-kudos:hover {
    transform: scale(1.12);
    background: var(--bg-inset-strong);
}

/* -------------------------------------------------------------- feed */

.pulse-indicator {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-break);
    box-shadow: 0 0 10px var(--color-break);
    animation: pulse 2s infinite;
}

@keyframes pulse {
    0%, 100% { transform: scale(0.95); opacity: 0.8; }
    50% { transform: scale(1.2); opacity: 1; }
}

.quick-reactions-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 0 14px;
    border-bottom: 1px solid var(--panel-border);
    margin-bottom: 14px;
}

.reaction-target {
    padding: 5px 9px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-sm);
    color: var(--text-main);
    font-family: var(--font-body);
    font-size: 0.8rem;
    outline: none;
    cursor: pointer;
    max-width: 170px;
}

.reaction-target:focus {
    border-color: var(--accent-blue);
}

.reactions-label {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-muted);
}

.btn-reaction {
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-sm);
    padding: 4px 9px;
    font-size: 1.05rem;
    cursor: pointer;
    transition: transform 0.15s ease, background 0.15s ease;
}

.btn-reaction:hover {
    background: var(--bg-inset-strong);
    transform: scale(1.15);
}

.feed-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 190px;
    overflow-y: auto;
}

.feed-item {
    font-size: 0.84rem;
    padding: 8px 12px;
    background: var(--bg-inset);
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--accent-blue);
}

.feed-empty {
    color: var(--text-dim);
    font-size: 0.84rem;
    text-align: center;
    padding: 20px 0;
}

/* --------------------------------------------------- floating emoji */

#floating-kudos-container {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 2000;
}

.floating-kudos {
    position: absolute;
    font-size: 2.4rem;
    animation: floatUp 2.5s forwards ease-out;
}

/* The animation was referenced but never defined, so every kudos emoji
   appeared at a fixed spot and sat there until it was removed. */
@keyframes floatUp {
    0% { transform: translateY(0) scale(0.6); opacity: 0; }
    15% { transform: translateY(-20px) scale(1.15); opacity: 1; }
    100% { transform: translateY(-260px) scale(0.9); opacity: 0; }
}

/* ------------------------------------------------------------ toasts */

.toast {
    position: fixed;
    bottom: 24px;
    right: 24px;
    padding: 13px 20px;
    border-radius: var(--radius-md);
    z-index: 3000;
    font-size: 0.9rem;
    font-weight: 600;
    max-width: min(380px, calc(100vw - 48px));
    animation: toastIn 0.25s ease-out;
}

@keyframes toastIn {
    from { transform: translateY(12px); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
}

/* ------------------------------------------------------ focus history */

.stats-card {
    max-width: 760px;
    text-align: left;
}

.stats-card .modal-header {
    text-align: center;
}

.stat-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 12px;
    margin-bottom: 22px;
}

.stat-tile {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 14px 16px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-md);
}

.stat-tile-label {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
}

.stat-tile-value {
    font-family: var(--font-heading);
    font-size: 1.6rem;
    font-weight: 700;
    /* Proportional figures: tabular-nums makes a standalone value look loose at
       display sizes. The table below is where digits need to align. */
    color: var(--text-main);
}

.chart-figure {
    margin-bottom: 18px;
}

.chart-figure figcaption {
    font-size: 0.78rem;
    color: var(--text-muted);
    margin-bottom: 10px;
}

.chart-holder {
    width: 100%;
    overflow-x: auto;
}

.history-chart {
    width: 100%;
    height: auto;
    display: block;
}

.chart-bar {
    fill: var(--chart-bar);
    /* The 2px separation between neighbours is surface showing through, not a
       stroke — a border would add ink that is not data. */
    transition: opacity 0.15s ease;
}

.chart-bar:hover {
    opacity: 0.78;
}

.chart-grid {
    stroke: var(--chart-grid);
    stroke-width: 1;
    shape-rendering: crispEdges;
}

/* Text wears text tokens, never the series colour. */
.chart-tick,
.chart-axis {
    fill: var(--text-dim);
    font-family: var(--font-body);
    font-size: 10px;
    font-variant-numeric: tabular-nums;
}

.chart-axis-today {
    fill: var(--text-muted);
    font-weight: 700;
}

.chart-value {
    fill: var(--text-main);
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: 700;
}

.chart-table summary {
    cursor: pointer;
    font-size: 0.82rem;
    color: var(--text-muted);
    padding: 6px 0;
}

.data-table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 10px;
    font-size: 0.84rem;
}

.data-table th,
.data-table td {
    text-align: left;
    padding: 7px 10px;
    border-bottom: 1px solid var(--panel-border);
}

.data-table th {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-muted);
    font-weight: 600;
}

.data-table td:not(:first-child) {
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------- command centre */

/* Full width: it is the only panel on screen while it is showing. */
.command-card {
    grid-column: 1 / -1;
}

.command-room + .command-room {
    margin-top: 18px;
}

.command-room-name {
    display: flex;
    align-items: baseline;
    gap: 10px;
    font-family: var(--font-heading);
    font-size: 0.95rem;
    font-weight: 600;
    margin-bottom: 8px;
}

.command-room-count {
    font-family: var(--font-body);
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 0.4px;
}

.command-rows {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.command-row {
    display: grid;
    grid-template-columns: minmax(140px, 1.1fr) minmax(0, 2.4fr) auto minmax(78px, auto);
    align-items: center;
    gap: 14px;
    padding: 9px 12px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-left: 3px solid var(--color-away);
    border-radius: var(--radius-sm);
}

.command-row.status-focus { border-left-color: var(--color-focus); }
.command-row.status-break { border-left-color: var(--color-break); }
.command-row.status-planning { border-left-color: var(--color-planning); }
.command-row.status-away { border-left-color: var(--color-away); opacity: 0.7; }

.command-who {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
}

.command-who .member-avatar {
    width: 28px;
    height: 28px;
    font-size: 0.78rem;
}

.command-what {
    min-width: 0;
}

.command-task {
    font-size: 0.86rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.command-note {
    font-size: 0.74rem;
    color: var(--accent-gold);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.command-remaining {
    text-align: right;
    font-family: var(--font-mono);
    font-size: 0.86rem;
    font-weight: 700;
    margin-bottom: 0;
    font-variant-numeric: tabular-nums;
}

.command-idle {
    color: var(--text-dim);
    font-weight: 400;
}

/* Stacked on a phone: four columns in 375px would crush the task text, which
   is the one column actually worth reading. */
@media (max-width: 720px) {
    .command-row {
        grid-template-columns: 1fr auto;
        row-gap: 6px;
    }
    .command-what {
        grid-column: 1 / -1;
    }
}

/* ------------------------------------------------------------ kanban */

.kanban-card {
    margin-top: 0;
}

.kanban-add-form {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.kanban-add-form input {
    flex: 1 1 220px;
    min-width: 0;
    padding: 9px 14px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-md);
    color: var(--text-main);
    font-family: var(--font-body);
    font-size: 0.88rem;
    outline: none;
}

.kanban-add-form input:focus {
    border-color: var(--accent-blue);
}

.kanban-estimate-select {
    padding: 9px 12px;
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-md);
    color: var(--text-main);
    font-family: var(--font-body);
    font-size: 0.84rem;
    outline: none;
    cursor: pointer;
}

.kanban-board-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px;
    margin-top: 20px;
    /* Columns share a row height (not "start") so a short column's drop
       target still reaches as far down the page as a long sibling column —
       otherwise its box ends early and dragging a card from deep in a long
       Backlog has nowhere on-screen to drop it. */
    align-items: stretch;
}

@media (max-width: 860px) {
    .kanban-board-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.kanban-col {
    background: var(--bg-inset);
    border: 1px solid var(--panel-border);
    border-top: 3px solid var(--panel-border-strong);
    border-radius: var(--radius-md);
    padding: 16px;
    min-height: 300px;
    display: flex;
    flex-direction: column;
    transition: background 0.2s ease, border-color 0.2s ease;
}

.kanban-col[data-col="backlog"] { border-top-color: var(--accent-cyan); }
.kanban-col[data-col="in_progress"] { border-top-color: var(--color-focus); }
.kanban-col[data-col="done"] { border-top-color: var(--color-break); }

.kanban-col.drag-over {
    background: color-mix(in srgb, var(--accent-blue) 8%, transparent);
    border-color: var(--accent-blue);
}

.col-header h3 {
    font-family: var(--font-heading);
    font-size: 0.98rem;
    font-weight: 600;
    margin-bottom: 14px;
}

.kanban-task-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-height: 160px;
}

.kanban-item-card {
    background: var(--bg-card);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-md);
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    cursor: grab;
    transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

.kanban-item-card:active {
    cursor: grabbing;
}

.kanban-item-card:hover {
    transform: translateY(-2px);
    border-color: var(--panel-border-strong);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}

.kanban-item-card.dragging {
    opacity: 0.4;
    border: 2px dashed var(--accent-blue);
}

.kanban-task-title {
    font-size: 0.92rem;
    font-weight: 600;
    overflow-wrap: anywhere;
}

.kanban-task-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 0.74rem;
}

.assignee-badge {
    background: color-mix(in srgb, var(--accent-cyan) 14%, transparent);
    color: var(--accent-cyan);
    padding: 2px 8px;
    border-radius: var(--radius-full);
    font-weight: 600;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pomodoro-badge {
    background: color-mix(in srgb, var(--accent-gold) 14%, transparent);
    color: var(--accent-gold);
    padding: 2px 8px;
    border-radius: var(--radius-full);
    font-weight: 700;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    border: 1px solid color-mix(in srgb, var(--accent-gold) 30%, transparent);
    margin-left: auto;
}

.kanban-card-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    /* One line, always. The focus button used to flex to fill and shove the
       bin and the move arrows onto a second row, which cost a whole line of
       height on every card in the backlog. */
    flex-wrap: nowrap;
}

.kanban-move-group {
    display: flex;
    gap: 4px;
    margin-left: auto;
}

/* The keyboard and touch path for moving a card. Drag-and-drop never worked on
   touch and has no keyboard equivalent, so these are the primary control. */
.btn-kanban-move {
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--panel-border);
    background: var(--bg-inset-strong);
    color: var(--text-muted);
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    transition: all 0.15s ease;
}

.btn-kanban-move:hover {
    background: color-mix(in srgb, var(--accent-blue) 20%, transparent);
    border-color: color-mix(in srgb, var(--accent-blue) 40%, transparent);
    color: var(--accent-blue);
}

.kanban-item-card:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
    border-color: var(--accent-blue);
}

/* Comfortable touch targets on a phone, where this board was unusable. */
/* Width as well as pointer: `pointer: coarse` never matches a resized desktop
   browser, so a rule behind it alone cannot be verified here — and these are
   exactly the targets that need checking at phone width. */
@media (pointer: coarse), (max-width: 640px) {
    .btn-kanban-move,
    .btn-kanban-action {
        min-height: 40px;
        min-width: 40px;
    }

    .btn-step {
        width: 40px;
        height: 40px;
    }
}

.btn-kanban-action {
    /* Shrink before the icon buttons do, and never grow past what the label
       needs. `min-width: 0` is what actually permits the shrink — without it
       a flex item refuses to go below its content width and wraps instead. */
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 4px 7px;
    font-family: var(--font-body);
    font-size: 0.76rem;
    font-weight: 600;
    border-radius: var(--radius-sm);
    border: 1px solid var(--panel-border);
    background: var(--bg-inset);
    color: var(--text-main);
    cursor: pointer;
    transition: background 0.15s ease;
}

.btn-kanban-action:hover {
    background: var(--bg-inset-strong);
}

.btn-kanban-focus {
    background: color-mix(in srgb, var(--accent-blue) 14%, transparent);
    color: var(--accent-blue);
    border-color: color-mix(in srgb, var(--accent-blue) 30%, transparent);
}

.btn-kanban-focus:hover {
    background: color-mix(in srgb, var(--accent-blue) 28%, transparent);
}

.btn-kanban-archive {
    background: color-mix(in srgb, var(--color-break) 14%, transparent);
    color: var(--color-break);
    border-color: color-mix(in srgb, var(--color-break) 30%, transparent);
}

.btn-kanban-archive:hover {
    background: color-mix(in srgb, var(--color-break) 28%, transparent);
}

.btn-kanban-delete {
    flex: 0 0 auto;
    color: var(--text-dim);
    /* Square, like the move arrows beside it, so the row reads as one strip
       of controls rather than a button and some afterthoughts. */
    padding: 4px 6px;
}

.btn-kanban-delete:hover {
    color: var(--accent-rose);
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ── Team report ─────────────────────────────────────────────────────────── */

.report-range {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-secondary);
    font-family: inherit;
    font-size: 0.8rem;
    padding: 0.35rem 0.6rem;
}

.report-board {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin-top: 1rem;
}

.report-row {
    align-items: center;
    background: var(--surface-2);
    border-radius: 8px;
    display: grid;
    /* Rank and total are fixed so names and bars line up down the column
       regardless of how long anyone's name is. */
    grid-template-columns: 1.75rem minmax(0, 1fr) minmax(60px, 8rem) 4rem;
    gap: 0.75rem;
    padding: 0.55rem 0.75rem;
}

/* Present, but visibly not part of this week's story. */
.report-row-idle { opacity: 0.55; }

.report-rank {
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: 0.8rem;
    text-align: center;
}

.report-name {
    color: var(--text-primary);
    font-size: 0.9rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.report-detail {
    color: var(--text-muted);
    font-size: 0.72rem;
    margin-top: 0.1rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.report-bar-track {
    background: var(--surface-3, rgba(255, 255, 255, 0.06));
    border-radius: 999px;
    height: 6px;
    overflow: hidden;
}

.report-bar {
    background: linear-gradient(90deg, var(--accent-1), var(--accent-2));
    border-radius: 999px;
    height: 100%;
}

.report-minutes {
    color: var(--text-secondary);
    font-family: var(--font-mono);
    font-size: 0.82rem;
    text-align: right;
}

.stat-tile-hint {
    color: var(--text-muted);
    font-size: 0.68rem;
    margin-top: 0.15rem;
}

@media (max-width: 640px) {
    .report-row {
        grid-template-columns: 1.5rem minmax(0, 1fr) 3.5rem;
    }
    /* The bar is decoration; the number beside it is the fact. */
    .report-bar-track { display: none; }
}

/* ── Phones ──────────────────────────────────────────────────────────────── */

/*
 * The page now declares viewport-fit=cover so the background reaches under a
 * notch and rounded corners. That is only safe if the content is inset back
 * out again, which is what this does — without it the header sits under the
 * status bar on a modern iPhone.
 */
@media (max-width: 780px) {
    .app-header,
    #app-content,
    .login-modal .modal-card {
        padding-left: max(1rem, env(safe-area-inset-left));
        padding-right: max(1rem, env(safe-area-inset-right));
    }

    #app-content {
        padding-bottom: max(1.5rem, env(safe-area-inset-bottom));
    }
}

@media (max-width: 640px) {
    /*
     * The header was one nowrap row: room label, stats and theme in a pill
     * 341px wide inside a 375px viewport, which put its right edge 2px past
     * the screen and shaved the rounded corner off. Wrapping costs a line and
     * fixes it at every width rather than at the one that was measured.
     */
    .room-selector-wrapper {
        flex-wrap: wrap;
        justify-content: center;
        row-gap: 8px;
        padding: 8px 12px;
        border-radius: var(--radius-md);
        width: 100%;
    }

    .room-selector-wrapper .label {
        flex-basis: 100%;
        text-align: center;
    }

    /* Chips that scroll rather than wrap; the scrollbar itself is noise on a
       phone, and momentum makes the row feel like part of the page. */
    .status-filters {
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        scroll-snap-type: x proximity;
    }

    .status-filters::-webkit-scrollbar {
        display: none;
    }

    .filter-tab {
        scroll-snap-align: start;
    }
}

/*
 * Touch targets.
 *
 * `.btn-step` and the kanban buttons were already covered. These were not, and
 * they are the ones a phone actually needs: every panel starts collapsed, so
 * the toggle is the first thing anyone taps.
 *
 * Width is included as well as pointer, because a narrow window is the case
 * that can actually be tested — `pointer: coarse` does not apply to a resized
 * desktop browser, so a rule behind it alone is unverifiable here.
 */
@media (pointer: coarse), (max-width: 640px) {
    .panel-grip,
    .panel-toggle {
        width: 40px;
        height: 40px;
    }

    #stats-btn,
    #theme-toggle-btn,
    #tick-toggle-btn,
    #notify-btn,
    .btn-reaction {
        min-height: 40px;
    }

    /* The volume and duration inputs are drag targets, not just readouts. */
    #tick-volume {
        height: 40px;
    }
}

/* ── Hour strip ──────────────────────────────────────────────────────────── */

.hour-blocks {
    display: grid;
    /* 24 equal columns that shrink rather than overflow: minmax(0, 1fr) is the
       part that lets them go below their content width on a phone. */
    grid-template-columns: repeat(24, minmax(0, 1fr));
    gap: 2px;
}

.hour-block {
    background: color-mix(in srgb, var(--accent-blue) calc(var(--fill, 0) * 100%), transparent);
    border-radius: 3px;
    height: 34px;
}

.hour-block-empty {
    background: var(--bg-inset);
}

.hour-scale {
    color: var(--text-dim);
    display: flex;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    justify-content: space-between;
    margin-top: 4px;
}

@media (max-width: 640px) {
    /* Twenty-four blocks across 300px is ~11px each — still legible as a
       shape, which is all this is for. */
    .hour-block { height: 26px; }
}

/* ── Collapsible board columns ───────────────────────────────────────────── */

.col-header {
    align-items: center;
    display: flex;
    gap: 0.5rem;
    justify-content: space-between;
}

.col-toggle {
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-dim);
    cursor: pointer;
    font-size: 0.7rem;
    line-height: 1;
    padding: 4px 6px;
}

.col-toggle:hover {
    background: var(--bg-inset);
    color: var(--text-main);
}

/*
 * The list goes, the header and its count stay. A collapsed column still says
 * how much is in it, and — because the listeners live on .kanban-col, not on
 * the list — it is still a drop target, so a card can be dragged onto a folded
 * column's header.
 */
.col-collapsed .kanban-task-list {
    display: none;
}

.col-collapsed {
    /* Enough of a target to drop onto, and visibly a column rather than a gap. */
    min-height: 0;
    padding-bottom: 0.5rem;
}

@media (pointer: coarse), (max-width: 640px) {
    .col-toggle {
        min-height: 40px;
        min-width: 40px;
    }
}

/* ── Cards folded to one line ────────────────────────────────────────────── */

.kanban-toolbar {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 0.5rem;
}

.kanban-card-head {
    align-items: flex-start;
    display: flex;
    gap: 0.4rem;
    justify-content: space-between;
}

.card-fold {
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-dim);
    cursor: pointer;
    flex: 0 0 auto;
    font-size: 0.65rem;
    line-height: 1;
    padding: 3px 5px;
}

.card-fold:hover {
    background: var(--bg-inset);
    color: var(--text-main);
}

/*
 * Folded: the title and its control, nothing else. The title stops wrapping so
 * the card is genuinely one line high rather than "shorter" — a long title
 * ellipses instead of growing the card back.
 */
.card-folded .kanban-card-foot {
    display: none;
}

.card-folded .kanban-task-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.card-folded {
    padding-bottom: 0.5rem;
    padding-top: 0.5rem;
}

@media (pointer: coarse), (max-width: 640px) {
    .card-fold {
        min-height: 40px;
        min-width: 40px;
    }
}

/* Where a dragged card would land. */
.drop-marker {
    background: linear-gradient(90deg, var(--accent-blue), var(--accent-cyan));
    border-radius: 2px;
    height: 3px;
    margin: 2px 0;
    pointer-events: none;
}

/* When a card was added. Quiet — it is context, not a fact anyone acts on. */
.added-badge {
    color: var(--text-dim);
    font-family: var(--font-mono);
    font-size: 0.68rem;
    white-space: nowrap;
}

/* ── Card details, on hover or tap ───────────────────────────────────────── */

.card-info-wrap {
    flex: 0 0 auto;
    position: relative;
}

.card-info {
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-dim);
    cursor: pointer;
    font-size: 0.8rem;
    line-height: 1;
    padding: 3px 5px;
}

.card-info:hover,
.card-info:focus-visible {
    background: var(--bg-inset);
    color: var(--text-main);
}

.card-details {
    background: var(--bg-raised);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-sm);
    box-shadow: 0 8px 24px rgb(0 0 0 / 45%);
    display: none;
    font-size: 0.72rem;
    left: auto;
    /* Anchored to the right edge of the control so it opens inwards; a card
       sits near the right of its column and a left-anchored panel would hang
       off the screen on a phone. */
    right: 0;
    min-width: 190px;
    max-width: min(260px, 78vw);
    padding: 0.5rem 0.6rem;
    position: absolute;
    top: calc(100% + 4px);
    z-index: 20;
}

/* Tapped open — the touchscreen path, and the one that survives a finger
   lifting off the control. */
.card-info-wrap.details-open .card-details {
    display: block;
}

/* Hover is the enhancement, and only where a pointer really exists. The
   wrapper is the target rather than the button, so moving onto the panel
   itself does not close it. */
@media (hover: hover) and (pointer: fine) {
    .card-info-wrap:hover .card-details,
    .card-info:focus-visible + .card-details {
        display: block;
    }
}

.card-detail-row {
    display: flex;
    gap: 0.6rem;
    justify-content: space-between;
    padding: 1px 0;
}

.card-detail-label {
    color: var(--text-dim);
}

.card-detail-value {
    color: var(--text-main);
    text-align: right;
}

@media (pointer: coarse), (max-width: 640px) {
    .card-info {
        min-height: 40px;
        min-width: 40px;
    }
    .card-details {
        font-size: 0.78rem;
    }
}

@media (pointer: coarse), (max-width: 640px) {
    /* Everything on the row is a thumb target, and the row still has to fit:
       40 + 40 + 40 plus gaps is about 130px inside a ~270px card. The focus
       label ellipses toward its icon rather than wrapping the row.

       Restated here, after the `min-width: 0` that lets the label shrink —
       that rule sits later in the file than the original touch-target block
       and was silently cancelling it, so the bin rendered 25px wide while its
       height was correctly 40. Same-specificity conflicts go to whichever
       comes last. */
    .kanban-card-actions {
        gap: 6px;
    }

    .btn-kanban-action,
    .btn-kanban-move,
    .btn-kanban-delete {
        min-height: 40px;
        min-width: 40px;
    }
}

/* ── The card's one footer line ──────────────────────────────────────────── */

.kanban-card-foot {
    align-items: center;
    display: flex;
    flex-wrap: nowrap;
    gap: 4px;
    margin-top: 0.4rem;
}

/* Buttons left, badges pushed to the right of them, move arrows last — so the
   pomodoro count lines up with the controls instead of floating on a row of
   its own.
   
   `flex-wrap: nowrap` overrides the `wrap` the badge row carried when it was a
   row of its own: wrapping there now buys a second line inside the footer,
   which is the very thing this removes. */
.kanban-card-foot .kanban-task-meta {
    align-items: center;
    display: flex;
    flex-wrap: nowrap;
    gap: 4px;
    justify-content: flex-end;
    margin-left: auto;
    min-width: 0;
}

.kanban-card-foot .kanban-card-actions {
    flex: 0 1 auto;
    min-width: 0;
}

.kanban-card-foot .kanban-move-group {
    margin-left: 0;
}

/* The assignee is the one thing here that can be long. It shrinks and ellipses
   rather than pushing the arrows off the card — the full name is in the ⓘ
   panel, so nothing is lost. */
.kanban-card-foot .assignee-badge {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 640px) {
    /* A name squeezed to "👤 S…" tells nobody anything, and it was costing the
       badges and arrows the width they need. The assignee is in the ⓘ panel,
       so hiding it here loses nothing and buys the rest of the row room to
       breathe. Kept on wider screens, where it fits honestly. */
    .kanban-card-foot .assignee-badge {
        display: none;
    }
}

/* ── Command Centre: every board, three columns ──────────────────────────── */

.command-board {
    display: grid;
    /* Three across where there is room, stacked where there is not — the same
       breakpoint the team board uses, so the two read alike. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
    margin-top: 1rem;
}

.command-column {
    background: var(--bg-inset);
    border-radius: var(--radius-md);
    min-width: 0;
    padding: 0.6rem;
}

.command-board .command-task-row {
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
}

.room-move-select {
    background: var(--bg-inset-strong);
    border: 1px solid var(--panel-border);
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-family: inherit;
    font-size: 0.68rem;
    margin-left: auto;
    max-width: 100%;
    padding: 2px 4px;
}

@media (max-width: 780px) {
    .command-board {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (pointer: coarse), (max-width: 640px) {
    .room-move-select {
        min-height: 40px;
    }
}

/* The member name doubles as its own rename control. */
.btn-chip-name {
    background: transparent;
    border: none;
    color: inherit;
    cursor: pointer;
    font: inherit;
    padding: 0;
}

.btn-chip-name:hover,
.btn-chip-name:focus-visible {
    text-decoration: underline;
}

/* Planning tools share the existing workspace's typography and controls. */
.productivity-card { grid-column: 1 / -1; padding: 1.5rem; min-width: 0; }
.productivity-card > details { border-top: 1px solid var(--border-color, #ffffff26); padding: 1rem 0; }
.productivity-card summary { cursor: pointer; font-weight: 600; min-height: 32px; }
.productivity-card .muted { opacity: .72; font-size: .9rem; margin: .5rem 0 1rem; }
.productivity-form { display: flex; flex-wrap: wrap; align-items: end; gap: .8rem; margin: 1rem 0; }
.productivity-form label, .productivity-card > details > label { display: flex; flex-direction: column; gap: .4rem; flex: 1 1 160px; }
.productivity-card input, .productivity-card select { max-width: 100%; min-height: 40px; padding: .5rem; border-radius: 8px; }
.productivity-card input[type=checkbox] { min-height: auto; width: 20px; height: 20px; }
.productivity-list { margin: .75rem 0; padding: 0; max-height: 480px; overflow-y: auto; }
.productivity-item { display: flex; align-items: center; flex-wrap: wrap; gap: .35rem; padding: .65rem 0; border-bottom: 1px solid #80808030; }
.productivity-item > span { flex: 1 1 220px; overflow-wrap: anywhere; }
.productivity-list > details { padding: .65rem 0; }
.productivity-card button { min-height: 40px; }
@media (max-width: 600px) { .productivity-card { padding: 1rem; } .productivity-form { align-items: stretch; } .productivity-form label { flex-basis: 100%; } }
.productivity-card input, .productivity-card select { background: var(--bg-inset); color: var(--text-main); border: 1px solid var(--panel-border-strong); font: inherit; }
.productivity-card select option { background: var(--select-option-bg); }
.productivity-card input:focus-visible, .productivity-card select:focus-visible { outline: 2px solid var(--accent-blue); outline-offset: 2px; }
.productivity-form label:has(input[type=checkbox]) { flex-direction: row; align-items: center; flex-basis: 100%; }
.productivity-card input[type=checkbox] { flex: 0 0 20px; accent-color: var(--accent-blue); }
