/* ==========================================================================
   Healthhub — design system

   Everything below is written against the tokens in this block, so a theme is
   a second block that redefines them and nothing else. Dark is the default;
   light is opted into and remembered in a cookie, which is why the theme is
   stamped on <html> by the server rather than applied by script — a page that
   picks its colours after paint flashes the wrong ones first.
   ========================================================================== */

:root {
    /* Surfaces, from furthest back to closest to the reader. */
    --bg: #0a0e14;
    --surface: #121821;
    --surface-2: #18202b;
    --surface-3: #1f2937;
    --border: #22303f;
    --border-strong: #31465c;

    /* Text */
    --text: #e6edf5;
    --text-muted: #8fa3b8;
    --text-faint: #61748a;

    /* Accents — these double as the metric series colors. */
    --accent: #6ea8fe;
    --accent-soft: rgba(110, 168, 254, 0.14);
    --accent-hover: #9cc4ff;
    /* What text sitting on top of a filled accent has to be. Flips with the
       theme: near-black reads on the pale blue, white on the deep one. */
    --on-accent: #06090f;
    --accent-grad-b: #8b7dfb;
    --accent-grad-hover-a: #86b8ff;
    --accent-grad-hover-b: #9a8dff;
    --teal: #5eead4;
    --violet: #c4b5fd;
    --rose: #fda4af;
    --amber: #fcd34d;
    --good: #4ade80;
    --bad: #f87171;

    /* Translucent surfaces, which can't be derived from the solid ones. */
    --header-bg: rgba(10, 14, 20, 0.78);
    --sticky-bg: rgba(18, 24, 33, 0.97);
    --scrim: rgba(4, 7, 11, 0.66);
    --hairline: rgba(10, 14, 20, 0.35);
    --scrollbar-hover: #3f5a75;
    --glow-a: rgba(110, 168, 254, 0.10);
    --glow-b: rgba(196, 181, 253, 0.08);

    --radius: 14px;
    --radius-sm: 9px;
    --radius-pill: 999px;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.28);
    --shadow-lg: 0 2px 4px rgba(0, 0, 0, 0.4), 0 18px 48px rgba(0, 0, 0, 0.42);

    --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Inter, Roboto, Helvetica, Arial, sans-serif;
    --transition: 140ms cubic-bezier(0.4, 0, 0.2, 1);

    color-scheme: dark;
}

/* Light. Same roles, different values — nothing below this block knows which
   theme it is drawing. The accents darken because a pale blue that reads well
   on near-black is close to invisible on white. */
:root[data-theme='light'] {
    --bg: #f4f7fb;
    --surface: #ffffff;
    --surface-2: #f1f5f9;
    --surface-3: #e4eaf1;
    --border: #dbe3ec;
    --border-strong: #b3c1d1;

    --text: #0f172a;
    --text-muted: #4a5a6d;
    --text-faint: #6b7c90;

    --accent: #2563eb;
    --accent-soft: rgba(37, 99, 235, 0.11);
    --accent-hover: #1d4ed8;
    --on-accent: #ffffff;
    --accent-grad-b: #6d4aff;
    --accent-grad-hover-a: #1d4ed8;
    --accent-grad-hover-b: #5b34f0;
    --teal: #0d9488;
    --violet: #7c3aed;
    --rose: #e11d48;
    --amber: #b45309;
    --good: #15803d;
    --bad: #dc2626;

    --header-bg: rgba(255, 255, 255, 0.82);
    --sticky-bg: rgba(255, 255, 255, 0.97);
    --scrim: rgba(15, 23, 42, 0.38);
    --hairline: rgba(15, 23, 42, 0.10);
    --scrollbar-hover: #8496a9;
    --glow-a: rgba(37, 99, 235, 0.07);
    --glow-b: rgba(124, 58, 237, 0.06);

    --shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 8px 24px rgba(15, 23, 42, 0.07);
    --shadow-lg: 0 2px 4px rgba(15, 23, 42, 0.08), 0 18px 48px rgba(15, 23, 42, 0.13);

    color-scheme: light;
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

/* The `hidden` attribute has to beat any `display` we set further down, or a
   script that hides a row leaves it on the page. The browser's own rule for
   it is a bare `[hidden]`, which loses to something as ordinary as
   `.quick-log li { display: flex }` — that is exactly how the favourites
   filter came to do nothing. */
[hidden] { display: none !important; }

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    font-family: var(--font);
    font-size: 14px;
    line-height: 1.5;
    color: var(--text);
    background-color: var(--bg);
    /* Two very soft pools of light so the page isn't a flat slab of black. */
    background-image:
        radial-gradient(900px 500px at 12% -8%, var(--glow-a), transparent 60%),
        radial-gradient(760px 460px at 88% 0%, var(--glow-b), transparent 62%);
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    margin: 0 0 0.5em;
    line-height: 1.25;
    font-weight: 650;
    letter-spacing: -0.015em;
}

h1 { font-size: 1.4rem; }
h2 { font-size: 1.1rem; }
h3 { font-size: 0.95rem; }

p { margin: 0 0 1em; }

a {
    color: var(--accent);
    text-decoration: none;
    transition: color var(--transition);
}

a:hover { color: var(--accent-hover); }

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}

/* ---------------------------------------------------------------- header --- */

.site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.4rem clamp(0.75rem, 3vw, 1.75rem);
    background: var(--header-bg);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--border);
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 1.05rem;
    font-weight: 680;
    letter-spacing: -0.02em;
    color: var(--text);
    white-space: nowrap;
}

.brand:hover { color: var(--text); }

.brand-mark {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 9px;
    background: linear-gradient(140deg, var(--accent), var(--violet));
    color: var(--on-accent);
    font-size: 15px;
}

/* Tabs */
.tabs {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-right: auto;
    overflow-x: auto;
    scrollbar-width: none;
}

.tabs::-webkit-scrollbar { display: none; }

.tab {
    position: relative;
    padding: 0.45rem 0.85rem;
    border-radius: var(--radius-sm);
    font-size: 0.92rem;
    font-weight: 550;
    color: var(--text-muted);
    white-space: nowrap;
    transition: color var(--transition), background var(--transition);
}

.tab:hover {
    color: var(--text);
    background: var(--surface-2);
}

.tab.is-active {
    color: var(--text);
    background: var(--accent-soft);
}

.tab.is-active::after {
    content: '';
    position: absolute;
    left: 0.85rem;
    right: 0.85rem;
    bottom: -0.78rem;
    height: 2px;
    border-radius: 2px;
    background: var(--accent);
}

.header-actions {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.user-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0.7rem 0.3rem 0.3rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--surface);
    font-size: 0.86rem;
    color: var(--text-muted);
}

.avatar {
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: linear-gradient(140deg, var(--accent), var(--violet));
    color: var(--on-accent);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
}

.logout-form { display: inline; }

/* Loud on purpose, and only ever on the test database — see core.runtime. */
.db-chip {
    padding: 0.1rem 0.5rem;
    border-radius: var(--radius-pill);
    background: var(--amber);
    color: var(--on-accent);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
}

.theme-form { display: inline-flex; }

/* Sized like the other icon buttons, but the glyph carries the meaning, so it
   gets a touch more of it. */
.theme-toggle {
    font-size: 1rem;
    line-height: 1;
    color: var(--text-muted);
}

.theme-toggle:hover { color: var(--text); }

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

main {
    flex: 1;
    width: 100%;
    max-width: 1240px;
    margin: 0 auto;
    padding: clamp(0.75rem, 2vw, 1.25rem) clamp(0.75rem, 3vw, 1.75rem) 2.5rem;
}

.page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.9rem;
}

.page-head h1 { margin-bottom: 0.1rem; }

.page-subtitle {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.site-footer {
    padding: 0.75rem;
    border-top: 1px solid var(--border);
    text-align: center;
    color: var(--text-faint);
    font-size: 0.84rem;
}

/* ------------------------------------------------------------------ cards --- */

.card {
    padding: 0.9rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.6rem;
}

.card-head h2,
.card-head h3 { margin: 0; }

.card-hint {
    color: var(--text-faint);
    font-size: 0.84rem;
}

/* A second, lesser heading inside a card, for a related form beneath the
   card's main one. */
.card-sub {
    margin: 0.8rem 0 0.45rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--border);
    color: var(--text-muted);
    font-size: 0.84rem;
    font-weight: 600;
}

/* ------------------------------------------------------------------ forms --- */

.field-input,
input[type='text'],
input[type='password'],
input[type='email'],
input[type='number'],
input[type='datetime-local'],
select {
    width: 100%;
    padding: 0.38rem 0.55rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--text);
    font-family: inherit;
    font-size: 0.94rem;
    transition: border-color var(--transition), box-shadow var(--transition);
}

.field-input:focus,
input:focus,
select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

select {
    appearance: none;
    /* Chevron drawn inline so there's no extra asset to ship. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5 6 8l3.5-3.5' fill='none' stroke='%238fa3b8' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.6rem center;
    background-size: 12px;
    padding-right: 2rem;
}

label {
    display: block;
    margin-bottom: 0.2rem;
    font-size: 0.8rem;
    font-weight: 550;
    color: var(--text-muted);
}

.form-field { margin-bottom: 0.6rem; }

/* Fields that are read across rather than down — the five macros, or an
   amount and its unit. They share the line evenly and wrap only when the
   basis really is too narrow, which keeps a phone usable. */
.field-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0 0.55rem;
}

.field-row > .form-field {
    flex: 1 1 4.5rem;
    min-width: 0;
}

/* Five labels across is tight, so they give up a little size rather than
   wrapping onto a second line and leaving the row ragged. */
.field-row > .form-field > label {
    font-size: 0.78rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.field-row .field-input { padding: 0.45rem 0.55rem; }

/* The unit of the chosen basis, drawn inside the amount box by unit-hint.js —
   "250 [g]" against one food is "250 [ml]" against another. */
.amount-wrap { position: relative; display: block; }
.unit-suffix {
    position: absolute;
    top: 50%;
    right: 0.55rem;
    transform: translateY(-50%);
    color: var(--text-faint);
    font-size: 0.8rem;
    pointer-events: none;
}
.amount-wrap input.has-unit { padding-right: 2.3rem; }

/* What one piece of a food is, beside its basis in the catalogue table. */
.basis-piece {
    color: var(--text-faint);
    font-size: 0.78rem;
    white-space: nowrap;
}

.helptext,
.form-field .helptext {
    display: block;
    margin-top: 0.3rem;
    color: var(--text-faint);
    font-size: 0.79rem;
}

.errorlist {
    margin: 0.4rem 0 0;
    padding-left: 1.1rem;
    color: var(--bad);
    font-size: 0.83rem;
}

/* Django's `as_p` output, brought into the design system. */
.styled-form p {
    margin: 0 0 0.9rem;
}

.styled-form p label {
    display: block;
    margin-bottom: 0.3rem;
}

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

.btn,
button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.4rem 0.8rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text);
    font-family: inherit;
    font-size: 0.92rem;
    font-weight: 550;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), transform var(--transition);
}

.btn:hover,
button:hover {
    background: var(--surface-3);
    border-color: var(--accent);
}

.btn:active,
button:active { transform: translateY(1px); }

.btn-primary {
    border-color: transparent;
    background: linear-gradient(140deg, var(--accent), var(--accent-grad-b));
    color: var(--on-accent);
    font-weight: 650;
}

.btn-primary:hover {
    border-color: transparent;
    background: linear-gradient(140deg, var(--accent-grad-hover-a), var(--accent-grad-hover-b));
}

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

.btn-ghost:hover {
    background: var(--surface-2);
    border-color: transparent;
    color: var(--text);
}

.btn-icon {
    padding: 0.3rem 0.5rem;
    font-size: 0.8rem;
}

.btn-block { width: 100%; }

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

/* Fixed, so an arriving message never shoves the page down under the cursor.
   Below the sticky header, above everything else. */
.toasts {
    position: fixed;
    top: 4.25rem;
    right: clamp(0.75rem, 4vw, 2.5rem);
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    width: min(340px, calc(100vw - 1.5rem));
    /* The stack itself must not swallow clicks meant for the page. */
    pointer-events: none;
}

.toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border-strong);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    box-shadow: var(--shadow-lg);
    color: var(--text);
    font-size: 0.85rem;
    line-height: 1.45;
    animation: toast-in 160ms cubic-bezier(0.4, 0, 0.2, 1);
}

.toast-success { border-left-color: var(--good); }
.toast-info    { border-left-color: var(--accent); }
.toast-warning { border-left-color: var(--amber); }
.toast-error   { border-left-color: var(--bad); }

.toast-text { flex: 1; }

.toast-close {
    flex: none;
    padding: 0 0.15rem;
    border: none;
    background: none;
    color: var(--text-faint);
    font-size: 0.8rem;
    line-height: 1.4;
    cursor: pointer;
}

.toast-close:hover { color: var(--text); }

.toast.is-going {
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 200ms ease, transform 200ms ease;
}

@keyframes toast-in {
    from { opacity: 0; transform: translateY(-6px); }
}

@media (prefers-reduced-motion: reduce) {
    .toast { animation: none; }
    .toast.is-going { transition: none; }
}

/* ---------------------------------------------------------- segmented UI --- */

.control-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem 1.25rem;
    padding: 0.85rem 1rem;
    margin-bottom: 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.control-group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.control-label {
    margin: 0;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-faint);
}

.segmented {
    display: inline-flex;
    padding: 3px;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--bg);
}

.segmented button {
    padding: 0.32rem 0.75rem;
    border: none;
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--text-muted);
    font-size: 0.84rem;
    font-weight: 550;
}

.segmented button:hover {
    background: var(--surface-2);
    color: var(--text);
}

.segmented button.is-active {
    background: var(--accent);
    color: var(--on-accent);
    font-weight: 650;
}

.toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.86rem;
    color: var(--text-muted);
    cursor: pointer;
    user-select: none;
}

.toggle input {
    width: 15px;
    height: 15px;
    accent-color: var(--accent);
    cursor: pointer;
}

/* Series on/off chips */
.series-toggles {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.series-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.32rem 0.8rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--bg);
    color: var(--text-muted);
    font-size: 0.85rem;
    font-weight: 550;
    cursor: pointer;
    transition: all var(--transition);
}

.series-chip:hover { border-color: var(--border-strong); }

.series-chip .swatch {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: currentColor;
    transition: opacity var(--transition);
}

.series-chip[aria-pressed='true'] {
    color: var(--text);
    border-color: var(--chip-color, var(--accent));
    background: color-mix(in srgb, var(--chip-color, var(--accent)) 14%, transparent);
}

.series-chip[aria-pressed='true'] .swatch {
    background: var(--chip-color, var(--accent));
}

.series-chip[aria-pressed='false'] {
    opacity: 0.55;
}

.series-chip[aria-pressed='false'] .swatch {
    background: var(--text-faint);
}

/* ------------------------------------------------------------ stat tiles --- */

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
    gap: 0.6rem;
    margin-bottom: 0.9rem;
}

.stat-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 0.6rem 0.8rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
    overflow: hidden;
    transition: border-color var(--transition), transform var(--transition);
}

.stat-tile:hover {
    border-color: var(--border-strong);
    transform: translateY(-1px);
}

/* Hairline of the series color along the top edge. */
.stat-tile::before {
    content: '';
    position: absolute;
    inset: 0 0 auto;
    height: 2px;
    background: var(--tile-color, var(--accent));
    opacity: 0.85;
}

.stat-label {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-faint);
}

.stat-label .swatch {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--tile-color, var(--accent));
}

.stat-value {
    font-size: 1.5rem;
    font-weight: 660;
    letter-spacing: -0.03em;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.stat-unit {
    margin-left: 0.2rem;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--text-faint);
}

.stat-meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.82rem;
    color: var(--text-faint);
}

.delta {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.1rem 0.45rem;
    border-radius: var(--radius-pill);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    background: var(--surface-3);
    color: var(--text-muted);
}

.delta.is-good { background: rgba(74, 222, 128, 0.14); color: var(--good); }
.delta.is-bad { background: rgba(248, 113, 113, 0.14); color: var(--bad); }

.stat-spark {
    margin-top: 0.35rem;
    height: 34px;
}

.stat-spark svg { display: block; width: 100%; height: 100%; }

/* --------------------------------------------------------------- charts --- */

.chart-grid {
    display: grid;
    gap: 1rem;
}

.chart-grid.is-separate {
    grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
}

.chart-grid.is-combined {
    grid-template-columns: 1fr;
}

.chart-card {
    display: flex;
    flex-direction: column;
    padding: 1.1rem 1.2rem 0.9rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.chart-card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.75rem;
}

.chart-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    font-size: 0.98rem;
    font-weight: 620;
}

.chart-title .swatch {
    width: 9px;
    height: 9px;
    border-radius: 50%;
}

.chart-range-note {
    font-size: 0.8rem;
    color: var(--text-faint);
    font-variant-numeric: tabular-nums;
}

.chart-plot {
    position: relative;
    width: 100%;
    height: 240px;
}

.chart-grid.is-combined .chart-plot { height: 380px; }

.chart-plot svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.chart-plot .axis-line { stroke: var(--border); stroke-width: 1; }
.chart-plot .grid-line { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 5; opacity: 0.55; }
.chart-plot .axis-text {
    fill: var(--text-faint);
    font-size: 11px;
    font-family: var(--font);
    font-variant-numeric: tabular-nums;
}
.chart-plot .series-line {
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.chart-plot .series-trend {
    fill: none;
    stroke-width: 1.5;
    stroke-dasharray: 5 4;
    opacity: 0.75;
}
.chart-plot .series-point {
    stroke: var(--surface);
    stroke-width: 1.5;
}
.chart-plot .series-bar { opacity: 0.85; }
.chart-plot .crosshair { stroke: var(--border-strong); stroke-width: 1; }
.chart-plot .hover-dot { stroke: var(--surface); stroke-width: 2; }

.chart-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1rem;
    margin-top: 0.6rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--border);
    font-size: 0.82rem;
    color: var(--text-muted);
}

.chart-legend .legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.chart-legend .swatch {
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

/* Tooltip */
.chart-tooltip {
    position: absolute;
    z-index: 10;
    min-width: 130px;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--sticky-bg);
    box-shadow: var(--shadow-lg);
    font-size: 0.82rem;
    pointer-events: none;
    opacity: 0;
    transform: translate(-50%, -110%);
    transition: opacity var(--transition);
}

.chart-tooltip.is-visible { opacity: 1; }

.chart-tooltip .tt-date {
    margin-bottom: 0.35rem;
    color: var(--text-faint);
    font-size: 0.76rem;
    letter-spacing: 0.02em;
}

.chart-tooltip .tt-row {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    white-space: nowrap;
}

.chart-tooltip .tt-row + .tt-row { margin-top: 0.2rem; }

.chart-tooltip .swatch {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: none;
}

.chart-tooltip .tt-value {
    margin-left: auto;
    font-weight: 620;
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------ empty state --- */

.empty-state {
    display: grid;
    place-items: center;
    gap: 0.4rem;
    padding: 3rem 1.5rem;
    text-align: center;
    color: var(--text-faint);
}

.empty-state .empty-icon {
    font-size: 1.8rem;
    opacity: 0.6;
}

.empty-state strong {
    color: var(--text-muted);
    font-weight: 600;
}

.empty-state code {
    padding: 0.15rem 0.4rem;
    border: 1px solid var(--border);
    border-radius: 5px;
    background: var(--bg);
    font-size: 0.85em;
    color: var(--accent);
}

/* ------------------------------------------------------------ log + table --- */

.dashboard-lower {
    display: grid;
    grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
    gap: 0.75rem;
    margin-top: 0.9rem;
    align-items: start;
}

/* For a split that sits directly under its own heading, which has already
   supplied the space above it. */
.dashboard-lower.is-tight { margin-top: 0; }

.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.89rem;
}

.data-table th {
    padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--border);
    text-align: left;
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-faint);
}

.data-table td {
    padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--border);
    color: var(--text-muted);
}

.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover td { background: var(--surface-2); }

.data-table .cell-metric {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text);
    font-weight: 550;
}

.data-table .cell-metric .swatch {
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.data-table .cell-value {
    color: var(--text);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.data-table .cell-actions {
    width: 1%;
    text-align: right;
}

.table-scroll {
    max-height: 420px;
    overflow-y: auto;
}

/* --------------------------------------------------------------- auth page --- */

.auth-layout {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
    gap: 1.25rem;
    max-width: 820px;
    margin: 0 auto;
}

.hero {
    padding: clamp(1.75rem, 5vw, 3rem);
    margin-bottom: 1.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background:
        radial-gradient(600px 300px at 15% 0%, rgba(110, 168, 254, 0.13), transparent 65%),
        var(--surface);
    box-shadow: var(--shadow);
}

.hero h1 {
    font-size: clamp(1.7rem, 4vw, 2.4rem);
    margin-bottom: 0.4rem;
}

.hero p {
    max-width: 54ch;
    color: var(--text-muted);
    font-size: 1rem;
}

.hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-top: 1.25rem;
}

.feature-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
    gap: 1rem;
}

.feature-card {
    padding: 1.1rem 1.2rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.feature-card h3 {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.98rem;
    margin-bottom: 0.35rem;
}

.feature-card p {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.89rem;
}

/* --------------------------------------------------------------- profile --- */

.detail-list {
    display: grid;
    gap: 0.1rem;
    margin: 0;
}

.detail-list div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.4rem 0;
    border-bottom: 1px solid var(--border);
}

.detail-list div:last-child { border-bottom: none; }

.detail-list dt {
    color: var(--text-faint);
    font-size: 0.88rem;
}

.detail-list dd {
    margin: 0;
    font-weight: 550;
    text-align: right;
}

/* ------------------------------------------------------------ week view --- */

.week-nav {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.week-label {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.94rem;
    font-weight: 600;
    white-space: nowrap;
}

.btn.is-disabled {
    opacity: 0.35;
    pointer-events: none;
}

.week-card { margin-bottom: 1.5rem; }

/* Seven day cards sharing one scale — together they are the chart. */
.week-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 0.6rem;
}

.day-card {
    display: flex;
    flex-direction: column;
    min-width: 0;
    padding: 0.7rem 0.6rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    transition: border-color var(--transition);
}

.day-card:hover { border-color: var(--border-strong); }

.day-card.is-today {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 7%, var(--bg));
}

.day-card.is-future { opacity: 0.5; }

.day-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.3rem;
    margin-bottom: 0.4rem;
}

.day-name {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.day-card.is-today .day-name { color: var(--accent); }

.day-date {
    font-size: 0.72rem;
    color: var(--text-faint);
    white-space: nowrap;
}

.day-kcal {
    font-size: 1.15rem;
    font-weight: 650;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}

.day-kcal-unit {
    margin-left: 0.15rem;
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--text-faint);
}

.day-kcal-empty { color: var(--text-faint); }

/* The bar itself: track is the full height, bar is scaled to the week's peak. */
.day-bar-track {
    display: flex;
    align-items: flex-end;
    height: 96px;
    margin: 0.5rem 0 0.6rem;
    border-bottom: 1px solid var(--border);
}

.day-bar {
    display: flex;
    flex-direction: column-reverse;
    width: 100%;
    min-height: 0;
    border-radius: 4px 4px 0 0;
    overflow: hidden;
}

.day-bar-segment {
    display: block;
    width: 100%;
    min-height: 2px;
    /* Hairline so two stacked segments of similar weight stay distinguishable. */
    box-shadow: inset 0 1px 0 var(--hairline);
}

.day-sessions {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Two rows, not one: in a seventh-of-a-page column there is no width to
 * share, and a single row lets the nowrap duration squeeze the workout name
 * out of existence. */
.session-chip {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas:
        'swatch label edit delete'
        '.      meta  meta meta';
    align-items: center;
    gap: 0 0.35rem;
    padding: 0.3rem 0.4rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface-2);
    font-size: 0.74rem;
}

.session-chip .swatch {
    grid-area: swatch;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--chip-color, var(--accent));
}

.session-label {
    grid-area: label;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.session-meta {
    grid-area: meta;
    color: var(--text-faint);
    font-variant-numeric: tabular-nums;
    line-height: 1.35;
}

.session-chip form {
    grid-area: delete;
    line-height: 0;
}

.session-delete {
    padding: 0.1rem 0.25rem;
    font-size: 0.68rem;
    opacity: 0;
    transition: opacity var(--transition);
}

.session-edit {
    grid-area: edit;
    padding: 0.1rem 0.25rem;
    font-size: 0.68rem;
    opacity: 0;
}

.session-chip:hover .session-delete,
.session-chip:hover .session-edit,
.session-edit:focus-visible,
.session-delete:focus-visible { opacity: 1; }

.day-rest {
    padding: 0.28rem 0;
    color: var(--text-faint);
    font-size: 0.74rem;
    font-style: italic;
}

/* A day's combined macros on the nutrition week, one small row per figure. */
.day-macros {
    display: grid;
    gap: 0.1rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 0.74rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.day-macros li {
    display: flex;
    justify-content: space-between;
}

.day-macro-label { font-weight: 650; }

@media (max-width: 900px) {
    /* Seven columns stop being legible long before the page gets narrow. */
    .week-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .day-bar-track { height: 64px; }
}

@media (max-width: 520px) {
    .week-grid { grid-template-columns: 1fr; }
}

/* --------------------------------------------------- callouts + statuses --- */

.callout {
    padding: 0.9rem 1.1rem;
    margin-bottom: 1.5rem;
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text-muted);
    font-size: 0.89rem;
    line-height: 1.6;
}

.callout strong { color: var(--text); }

.callout-warning {
    border-left-color: var(--amber);
    background: linear-gradient(90deg, rgba(252, 211, 77, 0.06), transparent 55%), var(--surface);
}

.status-pill {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.6rem;
    border-radius: var(--radius-pill);
    background: var(--surface-3);
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
}

.status-pill.is-good { background: rgba(74, 222, 128, 0.14); color: var(--good); }
.status-pill.is-warn { background: rgba(252, 211, 77, 0.14); color: var(--amber); }
.status-pill.is-bad { background: rgba(248, 113, 113, 0.14); color: var(--bad); }

.log-message {
    padding-top: 0 !important;
    color: var(--text-faint) !important;
    font-size: 0.82rem;
}

.disclosure {
    margin-top: 1rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--border);
}

.disclosure > summary {
    cursor: pointer;
    color: var(--text-muted);
    font-size: 0.85rem;
    font-weight: 550;
    list-style: none;
    user-select: none;
}

.disclosure > summary::-webkit-details-marker { display: none; }

.disclosure > summary::before {
    content: '▸';
    display: inline-block;
    margin-right: 0.4rem;
    color: var(--text-faint);
    transition: transform var(--transition);
}

.disclosure[open] > summary::before { transform: rotate(90deg); }

.disclosure > summary:hover { color: var(--text); }

.disclosure > form { margin-top: 0.9rem; }

.swatch-inline {
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: 0.4rem;
    border-radius: 50%;
    vertical-align: middle;
}

/* --------------------------------------------------------------- food db --- */

/* A vertical stack of cards inside one grid column. */
.stack {
    display: grid;
    gap: 0.75rem;
    align-items: start;
}

/* Foods and Meals are peers on the page, separated the way provider panels are. */
.db-section { margin-top: 1rem; scroll-margin-top: 4rem; }

.db-section + .db-section {
    margin-top: 1.4rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

.section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem 1rem;
    margin-bottom: 0.75rem;
}

.section-head h2 {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    margin: 0;
    font-size: 1.05rem;
}

.section-count {
    color: var(--text-faint);
    font-size: 0.8rem;
    font-weight: 500;
}

/* Search and create, on the heading's own line rather than a bar of their
   own — one fewer row between the top of the page and the data. */
.section-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
}

.section-tools .filter-search .field-input {
    width: clamp(150px, 20vw, 230px);
    padding: 0.3rem 0.55rem;
    font-size: 0.85rem;
}

/* ----- filters ----- */

.filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.filter-search {
    display: flex;
    gap: 0.4rem;
}

.filter-search .field-input {
    width: clamp(180px, 26vw, 280px);
    padding: 0.35rem 0.6rem;
}

.filter-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.tag-filter {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}

/* Chips stacked under their own caption, for a filter that lives in a column
   rather than strung along a bar. */
.filter-group + .filter-group { margin-top: 0.7rem; }

.filter-group > .card-hint {
    display: block;
    margin-bottom: 0.35rem;
}

a.tag-chip {
    text-decoration: none;
    transition: background var(--transition), color var(--transition);
}

a.tag-chip:hover {
    background: var(--surface-2);
    color: var(--text);
}

a.tag-chip.is-active {
    background: var(--accent);
    color: var(--on-accent);
    font-weight: 650;
}

/* The user's own tags, outlined rather than filled, so that "lunch" and
   "mum's staples" don't read as coming from the same list. */
.tag-chip.is-custom {
    background: transparent;
    border: 1px dashed var(--border-strong);
    color: var(--text-faint);
}

a.tag-chip.is-custom:hover { border-color: var(--accent); color: var(--text); }

a.tag-chip.is-custom.is-active {
    border-style: solid;
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--text);
}

/* ----- collapsible create forms ----- */

/* Kept shut by default so a secondary form doesn't push the primary button
   out of reach; one that failed validation is opened by the template so its
   errors are seen. */
.panel {
    padding: 0.55rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
}

.panel > summary {
    cursor: pointer;
    color: var(--text-muted);
    font-size: 0.86rem;
    font-weight: 550;
    list-style: none;
    user-select: none;
}

.panel > summary::-webkit-details-marker { display: none; }

.panel > summary::before {
    content: '+';
    display: inline-block;
    width: 1rem;
    color: var(--text-faint);
    font-weight: 600;
}

.panel[open] > summary::before { content: '−'; }
.panel[open] > summary { color: var(--text); margin-bottom: 0.6rem; }
.panel > summary:hover { color: var(--text); }

/* The segmented control is a set of links here, not buttons — the scope lives
   in the URL so it survives a reload and can be linked to. */
.segmented a {
    padding: 0.32rem 0.75rem;
    border-radius: var(--radius-pill);
    color: var(--text-muted);
    font-size: 0.84rem;
    font-weight: 550;
    text-decoration: none;
}

.segmented a:hover {
    background: var(--surface-2);
    color: var(--text);
}

.segmented a.is-active {
    background: var(--accent);
    color: var(--on-accent);
    font-weight: 650;
}

.owner-chip {
    padding: 0.1rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    color: var(--text-faint);
    font-size: 0.75rem;
    font-weight: 550;
}

.tag-chip {
    padding: 0.1rem 0.5rem;
    border-radius: var(--radius-pill);
    background: var(--surface-3);
    color: var(--text-muted);
    font-size: 0.75rem;
    font-weight: 550;
}

/* ----- dense listing tables ----- */

.card.is-flush { padding: 0; overflow: hidden; }

.data-table.is-dense { font-size: 0.85rem; }

.data-table.is-dense th,
.data-table.is-dense td {
    padding: 0.18rem 0.5rem;
    line-height: 1.35;
}

/* The header stays put while a long listing scrolls under it. */
.data-table.is-dense thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--surface);
}

/* A group's first row gets the dividing line; rows within a group don't, so a
   food and its bases read as one block. */
.data-table.is-dense tbody td { border-bottom: none; }
.data-table.is-dense tbody tr.is-group-start > * { border-top: 1px solid var(--border); }
.data-table.is-dense tbody tr:first-child > * { border-top: none; }

/* Qualified by the table, because the group cell is a <th> and would
   otherwise lose to `.data-table th` — which shouts its contents in spaced
   capitals. That is right for a column heading and wrong for a food's name,
   and capitals are wider than the words they replace. */
.data-table th.cell-group {
    vertical-align: top;
    padding-right: 1rem;
    text-align: left;
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
    border-right: 1px solid var(--border);
    position: relative;
}

.group-name {
    display: block;
    color: var(--text);
    font-weight: 600;
    padding-right: 1.6rem;
}

.group-note,
.group-total {
    display: block;
    color: var(--text-faint);
    font-size: 0.78rem;
}

/* The Danish name rides on the English one's line rather than taking a row
   of its own — it is the same food said twice, not a second fact. */
.group-sub {
    color: var(--text-faint);
    font-size: 0.78rem;
    font-weight: 400;
}

.group-total {
    margin-top: 0.15rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.group-flags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-top: 0.2rem;
}

/* Tucked into the corner of the group cell so it costs no column of its own. */
.group-delete {
    position: absolute;
    top: 0.15rem;
    right: 0.3rem;
}

.cell-amount { white-space: nowrap; font-variant-numeric: tabular-nums; }
.cell-owner { color: var(--text-faint); font-size: 0.78rem; }
.cell-empty { color: var(--text-faint); font-style: italic; }

.table-scroll.is-tall { max-height: min(65vh, 640px); }

/* A lone checkbox reads better with its label beside it than above it. */
.checkbox-field {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
    user-select: none;
}

.checkbox-field input {
    width: 15px;
    height: 15px;
    accent-color: var(--accent);
    cursor: pointer;
}

/* Django wraps CheckboxSelectMultiple options in a div of their own. */
.checkbox-grid > div {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 0.9rem;
    margin-top: 0.35rem;
}

.checkbox-grid label {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--text-muted);
    font-size: 0.88rem;
    cursor: pointer;
}

.checkbox-grid label:hover { color: var(--text); }

.checkbox-grid input {
    accent-color: var(--accent);
    cursor: pointer;
}

.meal-total {
    margin-left: auto;
    color: var(--text-muted);
    font-size: 0.84rem;
    font-variant-numeric: tabular-nums;
}

/* Keeps a food's delete control at the far right of its heading row. */
.food-entry-head .entry-delete { margin-left: auto; }
.meal-total + .entry-delete { margin-left: 0.4rem; }

.cell-actions {
    width: 1%;
    text-align: right;
    white-space: nowrap;
}

/* Each destructive action is its own form, and a form is a block — so the
   icons stacked, and every row in the table was two buttons tall to hold
   them. Inline puts them side by side and halves the row. */
.cell-actions form { display: inline-flex; }

/* ----- favourites ----- */

.btn.is-starred { color: var(--amber); border-color: var(--amber); }

/* Capped rather than growing without limit: this card sits above the form
   that starts a log, and a long list would push that off the screen. */
.quick-log {
    display: grid;
    gap: 0.25rem;
    max-height: 15rem;
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
}

.is-compact-search {
    margin-bottom: 0.5rem;
    padding: 0.3rem 0.55rem;
    font-size: 0.85rem;
}

/* Qualified past `.quick-log li`, which would otherwise make this a flex
   container and leave its text stuck to one side. */
.quick-log li.quick-log-empty {
    display: block;
    padding: 0.5rem;
    color: var(--text-faint);
    font-size: 0.82rem;
    text-align: center;
}

.quick-log li {
    display: flex;
    align-items: stretch;
    gap: 0.2rem;
}

.quick-log li > form:first-child { flex: 1; min-width: 0; }

/* The whole row is the button — one press logs the plate again. */
.quick-log-go {
    display: block;
    width: 100%;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text);
    text-align: left;
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);
}

.quick-log-go:hover {
    border-color: var(--accent);
    background: var(--surface-3);
}

.quick-log-name {
    display: block;
    font-weight: 600;
    font-size: 0.88rem;
}

.quick-log-meta {
    display: block;
    color: var(--text-faint);
    font-size: 0.76rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ----- energy balance ----- */

/* Mirrored bars: the axis is where the plate meets the burn — in (amber)
   rises above it, out (violet) hangs below, one shared kcal scale. Both are
   faint context; the difference (in − out) is drawn solid in front, growing
   straight from the axis on the verdict's side. Two halves so the heights
   are simple percentages of each half. */
.balance-track {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 110px;
    margin: 0.35rem 0;
}

.balance-half { position: relative; flex: 1; }

.balance-half.is-up { border-bottom: 1px solid var(--border-strong); }

.balance-bar {
    position: absolute;
    left: 18%;
    right: 18%;
    border-radius: 3px;
}

.balance-bar.is-in { bottom: 0; background: var(--amber); border-radius: 3px 3px 0 0; opacity: 0.28; }
.balance-bar.is-out { top: 0; background: var(--violet); border-radius: 0 0 3px 3px; opacity: 0.28; }

/* The verdict bar: full colour, foreground, exactly the difference, from
   the axis out. */
.balance-bar.is-delta.is-surplus { bottom: 0; background: var(--rose); border-radius: 3px 3px 0 0; }
.balance-bar.is-delta.is-deficit { top: 0; background: var(--teal); border-radius: 0 0 3px 3px; }

.delta-surplus { color: var(--rose); }
.delta-deficit { color: var(--teal); }

/* A past day with nothing logged: present, but visibly not part of the sums. */
.day-card.is-untracked { opacity: 0.45; }

/* The month calendar: weeks stacked Monday to Sunday. */
.cal-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 3px;
    margin-bottom: 3px;
}

.cal-dayname {
    padding: 0.15rem 0.4rem;
    color: var(--text-faint);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.cal-cell {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-height: 62px;
    padding: 0.25rem 0.4rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
}

.cal-cell.is-today { border-color: var(--accent); }
.cal-cell.is-untracked { opacity: 0.45; }
.cal-cell.is-future { opacity: 0.35; background: transparent; }
/* A neighbouring month's spill-over: drawn so the weeks stay rectangular,
   faint so it never reads as part of this month. */
.cal-cell.is-out-month { opacity: 0.18; background: transparent; }

.cal-daynum { color: var(--text-faint); font-size: 0.72rem; }

.cal-delta {
    font-size: 0.9rem;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
}

.cal-empty { color: var(--text-faint); font-size: 0.8rem; }

/* A cell's headline figure when it isn't a signed delta. */
.cal-figure {
    color: var(--text);
    font-size: 0.9rem;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
}

/* One dot per session, in the workout type's colour. */
.cal-dots { display: flex; gap: 3px; }

.cal-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
}

.cal-meta {
    display: flex;
    gap: 0.4rem;
    margin-top: auto;
    color: var(--text-faint);
    font-size: 0.68rem;
    font-variant-numeric: tabular-nums;
}

/* ----- Ask Claude ----- */

.upgrade-note {
    margin: 0 0 0.5rem;
    color: var(--text-muted);
    font-size: 0.88rem;
}

.question-list { display: grid; gap: 0.6rem; }

.question {
    padding: 0.6rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
}

.question-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.3rem;
}

.question-head form { margin-left: auto; }

.question-text { margin: 0 0 0.3rem; font-weight: 600; font-size: 0.9rem; }

/* The answer reads as the reply it is: quieter, indented off the question. */
.question-answer {
    margin: 0 0 0.3rem;
    padding-left: 0.6rem;
    border-left: 2px solid var(--border-strong);
    color: var(--text-muted);
    font-size: 0.88rem;
    white-space: pre-line;
}

/* ----- FDTU search results ----- */

.fdtu-search { display: flex; gap: 0.35rem; margin-bottom: 0.4rem; }

.fdtu-results {
    display: grid;
    gap: 0.2rem;
    max-height: 16rem;
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* The whole row is the link — one press opens the prefilled form. */
.fdtu-results a {
    display: block;
    padding: 0.3rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text);
    transition: border-color var(--transition), background var(--transition);
}

.fdtu-results a:hover { border-color: var(--accent); background: var(--surface-3); }

.fdtu-name { display: block; font-size: 0.85rem; font-weight: 600; }

.fdtu-meta {
    display: block;
    color: var(--text-faint);
    font-size: 0.74rem;
    font-variant-numeric: tabular-nums;
}

.fdtu-more {
    padding: 0.3rem 0.5rem;
    color: var(--text-faint);
    font-size: 0.76rem;
    font-style: italic;
}

/* Icon buttons in a dense table earn their padding back. */
.data-table.is-dense .btn-icon {
    padding: 0.05rem 0.3rem;
    font-size: 0.78rem;
}

.food-entry {
    padding: 1rem 0;
    border-bottom: 1px solid var(--border);
}

.food-entry:first-of-type { padding-top: 0.25rem; }
.food-entry:last-of-type { padding-bottom: 0; border-bottom: none; }

.food-entry-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.6rem;
    margin-bottom: 0.5rem;
}

.food-entry-head h4 {
    margin: 0;
    font-size: 1rem;
}

.food-danish {
    color: var(--text-faint);
    font-size: 0.88rem;
}

.food-entry-description { margin: 0 0 0.6rem; }

.food-entry-empty { margin: 0; }

/* -------------------------------------------------- provider panels --- */

/* Each connected service on the profile page. The rule under it gives every
   panel after the first a separating line, so they read as a stack of peers
   rather than one long page. */
.section-divider {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

.section-divider h2 { margin-bottom: 0.15rem; }

.provider-panel {
    display: block;
    margin-top: 1.25rem;
    /* Anchored from the dashboard and week view, so keep the sticky header
       from covering the heading when one of those links is followed. */
    scroll-margin-top: 5rem;
}

.provider-panel + .provider-panel {
    margin-top: 1.5rem;
    padding-top: 2rem;
    border-top: 1px solid var(--border);
}

.provider-panel .page-head { margin-bottom: 1rem; }

/* ----------------------------------------------------------------- diary --- */

.diary-day + .diary-day {
    margin-top: 1.4rem;
    padding-top: 1.1rem;
    border-top: 1px solid var(--border);
}

.diary-day-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.4rem 1rem;
    margin-bottom: 0.5rem;
}

.diary-day-head h3 {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    font-size: 0.95rem;
}

.diary-day-total {
    color: var(--text-muted);
    font-size: 0.82rem;
    font-variant-numeric: tabular-nums;
}

.meal-link {
    color: var(--text);
    font-weight: 600;
    text-decoration: none;
}

.meal-link:hover { color: var(--accent); text-decoration: underline; }

/* One sitting's worth of a day — breakfast, lunch, whatever the tag says. */
.slot-group + .slot-group > tr:first-child > * { border-top: 1px solid var(--border); }

.slot-head > * {
    background: var(--surface-2);
    color: var(--text-muted);
}

.slot-head th {
    text-align: left;
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-faint);
}

.slot-count {
    display: inline-block;
    min-width: 1.15rem;
    margin-left: 0.35rem;
    padding: 0 0.32rem;
    border-radius: var(--radius-pill);
    background: var(--surface-3);
    color: var(--text-muted);
    font-size: 0.72rem;
    font-weight: 650;
    letter-spacing: 0;
    text-align: center;
}

/* Indented so a meal reads as sitting under its heading. */
.slot-member { padding-left: 1.4rem !important; }

.entry-name { color: var(--text); }

/* Resizing one line of a logged meal, inline in its own row. */
.amount-form {
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

.field-input.is-compact {
    width: 5.5rem;
    padding: 0.2rem 0.4rem;
    font-size: 0.82rem;
}

.amount-unit { color: var(--text-faint); font-size: 0.8rem; }

.field-checkbox {
    width: 15px;
    height: 15px;
    accent-color: var(--accent);
    cursor: pointer;
}

/* --------------------------------------------------- builder and scaling --- */

/* Both pages use .dashboard-lower, the app's standing arrangement: what you
   press on the left, what it acts on to the right. */

/* One dish on the plate, or the loose foods. Name, figures and controls all
   share one bar; it wraps only when the column can't hold them. */
.meal-box-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.6rem;
    padding: 0.35rem 0.6rem;
    border-bottom: 1px solid var(--border);
}

.meal-box-bar h3 {
    margin: 0;
    font-size: 0.92rem;
}

.meal-box-bar .card-hint {
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
}

.meal-box-tools {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    margin-left: auto;
}

.portion-inline {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.portion-inline label {
    color: var(--text-faint);
    font-size: 0.78rem;
}

.portion-inline .field-input.is-compact {
    width: 4.4rem;
    padding: 0.15rem 0.35rem;
    font-size: 0.8rem;
}

/* A button that sits comfortably on a one-line bar. */
.btn.btn-compact {
    padding: 0.2rem 0.5rem;
    font-size: 0.78rem;
}

.portion-card .card-head { margin-bottom: 0.6rem; }

.scale-current {
    font-variant-numeric: tabular-nums;
    color: var(--text);
    font-weight: 600;
}

.portion-form { display: flex; flex-direction: column; gap: 0.55rem; }

.scale-row {
    display: grid;
    grid-template-columns: 1fr auto auto;
    align-items: center;
    gap: 0.5rem;
}

.scale-row label {
    color: var(--text-muted);
    font-size: 0.88rem;
}

/* Rendered server-side when the URL asks for it, so it needs no script. */
.modal-scrim {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: grid;
    place-items: start center;
    padding: clamp(1rem, 6vh, 4rem) 1rem;
    overflow-y: auto;
    background: var(--scrim);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}

/* The backdrop as a link, so clicking off the card closes it without script.
   Fixed rather than absolute: the scrim scrolls when a form is taller than
   the screen, and an absolute link would scroll away with it, leaving the
   backdrop dead once you had scrolled down. */
.modal-dismiss {
    position: fixed;
    inset: 0;
    cursor: default;
}

/* Wide enough for the five macros to sit across one line without the boxes
   getting too narrow to read the number back in. */
.modal-card {
    /* Positioned, and above the backdrop link: a positioned element paints
       over an unpositioned one, so without this the link would swallow every
       click meant for the form inside. */
    position: relative;
    z-index: 1;
    width: min(620px, 100%);
    box-shadow: var(--shadow-lg);
}

.modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

/* A second way out, kept away from the pair that close or confirm. */
.modal-alt { margin-right: auto; }

/* ----- barcodes ----- */

.scan-form {
    margin-top: 0.7rem;
    padding-top: 0.7rem;
    border-top: 1px solid var(--border);
}

.scan-camera { margin-top: 0.4rem; }

.photo-scan { margin-top: 0.4rem; }

/* The real input is hidden and driven by its label, which is the only way to
   make a file picker look like the buttons beside it. */
.photo-scan label.btn {
    display: block;
    cursor: pointer;
    text-align: center;
}

.photo-scan-go { margin-top: 0.4rem; }

.scan-video {
    display: block;
    width: 100%;
    margin-top: 0.5rem;
    border-radius: var(--radius-sm);
    background: #000;
}

.barcode-chip {
    padding: 0.05rem 0.4rem;
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius-pill);
    color: var(--text-faint);
    font-size: 0.72rem;
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------ searchable select --- */

.combo { position: relative; }

.combo-list {
    position: absolute;
    z-index: 40;
    left: 0;
    right: 0;
    top: calc(100% + 4px);
    max-height: 240px;
    margin: 0;
    padding: 0.25rem;
    overflow-y: auto;
    list-style: none;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    box-shadow: var(--shadow-lg);
}

.combo-option {
    padding: 0.35rem 0.55rem;
    border-radius: 6px;
    color: var(--text-muted);
    font-size: 0.88rem;
    cursor: pointer;
}

.combo-option.is-muted { color: var(--text-faint); font-style: italic; }

.combo-option:hover,
.combo-option.is-active {
    background: var(--accent-soft);
    color: var(--text);
}

.combo-empty {
    padding: 0.45rem 0.55rem;
    color: var(--text-faint);
    font-size: 0.85rem;
    font-style: italic;
}

/* ------------------------------------------------------------------- a11y --- */

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* -------------------------------------------------------------- scrollbar --- */

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    border: 3px solid transparent;
    border-radius: var(--radius-pill);
    background-clip: content-box;
    background-color: var(--border-strong);
}
::-webkit-scrollbar-thumb:hover { background-color: var(--scrollbar-hover); }

/* ------------------------------------------------------------ logging pages --- */
/* The logger, the meal page and the recipe builder are one grid of named
   blocks each. Named areas rather than a left column and a right column so
   the phone can reorder the same blocks without the markup knowing. */

.logger,
.meal-page {
    display: grid;
    grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
    gap: 0.75rem;
    align-items: start;
}

.logger {
    grid-template-areas:
        'head head'
        'stats stats'
        'start eaten'
        'fav eaten';
}

.meal-page {
    grid-template-areas:
        'head head'
        'stats stats'
        'food plate'
        'recipe plate';
}

.logger-head, .meal-head { grid-area: head; margin-bottom: 0; }
.logger-stats, .meal-stats { grid-area: stats; margin-bottom: 0; }
.logger-start { grid-area: start; }
.logger-favourites { grid-area: fav; }
.logger-eaten { grid-area: eaten; }
.meal-add-food { grid-area: food; }
.meal-add-recipe { grid-area: recipe; }
.meal-plate { grid-area: plate; }

/* The name is a heading now, with the facts beneath it and the menu button
   on the right; nothing at the top is a form. */
.page-title-block { min-width: 0; }
.page-title {
    margin: 0;
    font-size: 1.35rem;
    font-weight: 650;
    letter-spacing: -0.015em;
    overflow-wrap: anywhere;
}
.page-title-block .page-subtitle { margin-top: 0.15rem; }
.page-tools {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-shrink: 0;
}
.menu-button { font-size: 1.1rem; line-height: 1; }

/* The rarer actions, in a row under the details form in the menu. */
.menu-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.9rem;
    padding-top: 0.7rem;
    border-top: 1px solid var(--border);
}

/* Starting a log: one thumb-sized button per sitting, stacked. */
.sitting-buttons {
    display: grid;
    gap: 0.4rem;
}
.sitting-button {
    width: 100%;
    padding: 0.6rem 0.8rem;
    font-size: 0.95rem;
    font-weight: 600;
    text-align: left;
}
.logger-when { margin: 0.7rem 0 0; }
.logger-when label { font-size: 0.78rem; color: var(--text-faint); }

/* Which of two renderings of the same thing a device gets. */
.only-phone { display: none; }

/* A day's meals as tap-targets, for the phone. No `display` of its own, so
   the .only-phone rule above decides whether it shows at all. */
.day-list-group + .day-list-group { margin-top: 0.6rem; }
.day-list-head {
    display: flex;
    justify-content: space-between;
    padding: 0 0.1rem 0.25rem;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-faint);
}
.day-list-row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.05rem 0.6rem;
    padding: 0.5rem 0.6rem;
    margin-bottom: 0.35rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text);
    text-decoration: none;
}
.day-list-name { font-weight: 600; font-size: 0.92rem; }
.day-list-time { font-size: 0.78rem; color: var(--text-faint); text-align: right; }
.day-list-kcal { font-weight: 600; font-size: 0.85rem; font-variant-numeric: tabular-nums; }
.day-list-macros { font-size: 0.76rem; color: var(--text-muted); text-align: right; white-space: nowrap; }
.day-list-items {
    grid-column: 1 / -1;
    font-size: 0.78rem;
    color: var(--text-faint);
    overflow-wrap: anywhere;
}

/* The star on a food: quiet until it is on. */
.star-form { display: inline; }
.star-button { padding: 0 0.25rem; font-size: 0.95rem; color: var(--text-faint); }
.star-button.is-starred { color: var(--amber); }
.group-tools { display: inline-flex; align-items: center; gap: 0.1rem; }
.entry-name + .star-form { margin-left: 0.2rem; }

/* Packaged products under the food table. */
.packaged { padding: 0 0.9rem 0.9rem; }
.packaged .card-sub { margin-top: 0.4rem; }

/* ------------------------------------------------------------ responsive --- */

@media (max-width: 900px) {
    .dashboard-lower { grid-template-columns: 1fr; }
    .chart-grid.is-separate { grid-template-columns: 1fr; }
    .logger,
    .meal-page { grid-template-columns: 1fr; }
    .logger { grid-template-areas: 'head' 'stats' 'start' 'fav' 'eaten'; }
    .meal-page { grid-template-areas: 'head' 'stats' 'food' 'recipe' 'plate'; }
}

@media (max-width: 720px) {
    .site-header {
        flex-wrap: wrap;
        gap: 0.6rem 1rem;
    }
    .tabs { order: 3; width: 100%; }
    .tab.is-active::after { bottom: -0.65rem; }
    .user-chip span:not(.avatar) { display: none; }
    .control-bar { gap: 0.75rem; }
    .chart-plot { height: 210px; }
}

/* ------------------------------------------------------------------ phone --- */
/* The phone is for logging; analysis lives on the computer. So on a small
   screen the figure boxes compress to one slim strip, every chart becomes a
   single swipeable row instead of a page-long stack, and the forms keep
   their size — they are the point of being here. Placed last on purpose:
   these override the tablet-width rules above by source order. */
@media (max-width: 640px) {
    main { padding: 0.6rem 0.6rem 2rem; }
    .card { padding: 0.65rem; }
    .page-head { margin-bottom: 0.6rem; gap: 0.5rem; }
    .site-footer { display: none; }

    /* The four figure boxes become one strip: numbers survive, ceremony
       doesn't. The meta line is the first thing a small screen can spare. */
    .stat-grid {
        /* However many tiles the page has share one row — the logger has
           five, most pages four; a fixed count strands the last one alone. */
        grid-auto-flow: column;
        grid-auto-columns: minmax(0, 1fr);
        grid-template-columns: none;
        gap: 0.3rem;
        margin-bottom: 0.6rem;
    }
    .stat-tile {
        gap: 0.05rem;
        padding: 0.3rem 0.4rem 0.25rem;
        border-radius: var(--radius-sm);
    }
    .stat-tile:hover { transform: none; }
    .stat-label {
        font-size: 0.56rem;
        letter-spacing: 0.02em;
        white-space: nowrap;
        overflow: hidden;
    }
    .stat-value { font-size: 0.95rem; }
    .stat-unit { font-size: 0.55rem; }
    .stat-meta { display: none; }

    /* Inputs at 16px, or iOS zooms the whole page on every focus — the
       single worst thing that can happen to quick logging. */
    .field-input,
    input[type='text'],
    input[type='search'],
    input[type='number'],
    input[type='email'],
    input[type='password'],
    input[type='datetime-local'],
    input[type='date'],
    select,
    textarea { font-size: 16px; }
    .field-input.is-compact { width: 5rem; }

    /* The buttons that log things stay thumb-sized. */
    .btn-block { padding-top: 0.55rem; padding-bottom: 0.55rem; }

    /* Week charts: one swipeable row, overriding the stacked-column rules
       above — seven cards down the page buried the forms under analysis. */
    .week-grid {
        display: flex;
        gap: 0.4rem;
        overflow-x: auto;
        padding-bottom: 0.3rem;
    }
    .week-grid > .day-card { flex: 0 0 128px; }
    .day-bar-track { height: 52px; }
    .balance-track { height: 60px; }
    .week-card > .card-head .card-hint { display: none; }
    .chart-legend { gap: 0.3rem 0.8rem; font-size: 0.72rem; }

    /* Month calendars: readable, not roomy. */
    .cal-cell { min-height: 44px; padding: 0.15rem 0.25rem; gap: 0; }
    .cal-meta { display: none; }
    .cal-delta,
    .cal-figure { font-size: 0.78rem; }

    /* Tables scroll sideways rather than squeezing their columns illegible. */
    .table-scroll { overflow-x: auto; }
    .data-table { font-size: 0.78rem; }
    .data-table th,
    .data-table td { padding: 0.28rem 0.4rem; white-space: nowrap; }

    /* Title bars and navigation give up their slack. */
    .page-title { font-size: 1.1rem; }
    .page-title-block .page-subtitle { font-size: 0.8rem; }
    .week-label { font-size: 0.85rem; }
    .week-nav { flex-wrap: wrap; gap: 0.35rem; }
    .segmented a { padding: 0.25rem 0.6rem; font-size: 0.8rem; }
    .provider-panel .dashboard-lower { gap: 0.6rem; }

    /* The logging pages: figures, then the thing you press, then the rest.
       The day's meals swap from a table to a list of tap-targets, and the
       time box goes — a phone log is now. */
    .logger,
    .meal-page { gap: 0.5rem; }
    .only-desktop { display: none; }
    .only-phone { display: block; }
    .logger-when { display: none; }
    .sitting-button { padding: 0.7rem 0.9rem; font-size: 1rem; }
    .meal-head { align-items: center; }
}

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