/* =========================================================================
   Office Days

   Mobile-first, and not as a slogan: the overwhelmingly common session is one
   person, on a phone, tapping one button, for about four seconds, often while
   walking through a door. Desktop is the secondary case — it gets more room
   and a different navigation, nothing more.

   No framework and no build step. That is a deployment constraint, not a
   preference: this ships as a zip over FTP to shared hosting, and a stylesheet
   that needs npm to regenerate is a stylesheet nobody will touch in a year.

   Everything below is plain CSS the browser understands directly. The modern
   parts — colour mixing, container queries, view transitions — are layered so
   that a browser without them still gets a complete, usable interface rather
   than a broken one.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. TOKENS

   OKLCH rather than hex for the accents. It is perceptually uniform, so
   lightening a colour by 10% looks like 10% rather than washing out — which
   is what makes the hover, active and subtle-background variants derivable
   from one value instead of hand-picked. Hex fallbacks are declared first;
   a browser that does not parse the oklch() line simply keeps the hex.
   ------------------------------------------------------------------------- */

:root {
    color-scheme: light dark;

    /* Neutrals */
    --bg: #f7f8fa;
    --surface: #ffffff;
    --surface-2: #f2f4f7;
    --border: #e3e7ed;
    --border-strong: #cbd3dd;
    --text: #131720;
    --text-muted: #5a6675;

    /* Accent */
    --accent: #2563eb;
    --accent: oklch(58% 0.19 258);
    --accent-hover: oklch(52% 0.19 258);
    --accent-text: #ffffff;
    --accent-soft: #e8effd;

    /* Status. Each is paired with a text colour that meets contrast on it. */
    --ok: #15803d;
    --ok: oklch(52% 0.14 150);
    --ok-soft: #e6f4ea;
    --warn: #b45309;
    --warn: oklch(58% 0.14 65);
    --warn-soft: #fdf1e3;
    --bad: #b42318;
    --bad: oklch(53% 0.19 27);
    --bad-soft: #fdeceb;

    /* Shape and depth. Two shadows only — a resting one and a raised one.
       More than that and nothing reads as deliberate. */
    --radius: 12px;
    --radius-sm: 8px;
    --radius-lg: 18px;
    --shadow: 0 1px 2px rgb(16 24 40 / 6%), 0 1px 3px rgb(16 24 40 / 8%);
    --shadow-lg: 0 4px 6px -2px rgb(16 24 40 / 4%), 0 12px 16px -4px rgb(16 24 40 / 10%);

    /* Spacing scale. A single ratio keeps rhythm consistent without anyone
       having to remember which of 14px or 16px was used last time. */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 24px;
    --sp-6: 32px;
    --sp-7: 48px;

    /* Fluid type: scales with the viewport between a phone and a laptop
       rather than stepping at a breakpoint. */
    --text-xs: 0.8125rem;
    --text-sm: 0.875rem;
    --text-base: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
    --text-lg: clamp(1.125rem, 1.08rem + 0.22vw, 1.25rem);
    --text-xl: clamp(1.375rem, 1.28rem + 0.45vw, 1.625rem);
    --text-2xl: clamp(1.75rem, 1.55rem + 1vw, 2.25rem);
}

/* -------------------------------------------------------------------------
   DARK PALETTE — three states, not two

   The theme has three possible values, and the CSS has to express all of them:

     "system"  no data-theme attribute; follow prefers-color-scheme
     "dark"    data-theme="dark";  dark regardless of the OS
     "light"   data-theme="light"; light regardless of the OS

   Hence the :not([data-theme="light"]) on the media query. Without it, a
   person whose OS is dark but who has chosen light in the app would get the
   media query's dark tokens anyway, and the toggle would appear to work in
   one direction only — which is the bug every hand-rolled theme switcher
   ships with at least once.

   The tokens are declared twice rather than pulled into a shared block: a
   @media and an attribute selector cannot be combined in one rule, and a
   custom property set indirected through another custom property is harder to
   read than the duplication it saves.
   ------------------------------------------------------------------------- */

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;
        --bg: #0d1117;
        --surface: #161b22;
        --surface-2: #1c232c;
        --border: #262d38;
        --border-strong: #3a434f;
        --text: #e8eaed;
        --text-muted: #98a3b3;

        --accent: #58a6ff;
        --accent: oklch(72% 0.15 253);
        --accent-hover: oklch(78% 0.15 253);
        --accent-text: #0b1220;
        --accent-soft: oklch(30% 0.07 253);

        --ok: oklch(76% 0.15 155);
        --ok-soft: oklch(28% 0.06 155);
        --warn: oklch(78% 0.14 70);
        --warn-soft: oklch(30% 0.06 70);
        --bad: oklch(70% 0.16 25);
        --bad-soft: oklch(28% 0.07 25);

        /* Shadows read as grime on a dark surface; depth comes from the
           surface steps instead. */
        --shadow: 0 1px 2px rgb(0 0 0 / 40%);
        --shadow-lg: 0 8px 24px rgb(0 0 0 / 45%);
    }
}

/* The same tokens again, for an explicit choice of dark on a light OS. */
:root[data-theme="dark"] {
    color-scheme: dark;
    --bg: #0d1117;
    --surface: #161b22;
    --surface-2: #1c232c;
    --border: #262d38;
    --border-strong: #3a434f;
    --text: #e8eaed;
    --text-muted: #98a3b3;

    --accent: #58a6ff;
    --accent: oklch(72% 0.15 253);
    --accent-hover: oklch(78% 0.15 253);
    --accent-text: #0b1220;
    --accent-soft: oklch(30% 0.07 253);

    --ok: oklch(76% 0.15 155);
    --ok-soft: oklch(28% 0.06 155);
    --warn: oklch(78% 0.14 70);
    --warn-soft: oklch(30% 0.06 70);
    --bad: oklch(70% 0.16 25);
    --bad-soft: oklch(28% 0.07 25);

    /* Shadows read as grime on a dark surface; depth comes from the
       surface steps instead. */
    --shadow: 0 1px 2px rgb(0 0 0 / 40%);
    --shadow-lg: 0 8px 24px rgb(0 0 0 / 45%);
}


:root[data-theme="light"] { color-scheme: light; }

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

/* Progressive: browsers with view transitions cross-fade between pages, so a
   multi-page app stops feeling like a series of reloads. Everything works
   identically without it. */
@view-transition { navigation: auto; }

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

    @view-transition { navigation: none; }
}

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

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, sans-serif;
    font-size: var(--text-base);
    line-height: 1.55;
    /* Respects the notch and home indicator once installed to the home screen,
       where there is no browser chrome keeping content clear of them. */
    padding: env(safe-area-inset-top) env(safe-area-inset-right)
             env(safe-area-inset-bottom) env(safe-area-inset-left);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    line-height: 1.2;
    letter-spacing: -0.015em;
    font-weight: 650;
}

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

/* -------------------------------------------------------------------------
   2. SIGNED-OUT PAGES
   ------------------------------------------------------------------------- */

body.centred {
    display: grid;
    place-items: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding: var(--sp-5);
    /* A quiet wash behind the card so the sign-in page is not a white slab. */
    background:
        radial-gradient(90rem 40rem at 50% -20%, var(--accent-soft), transparent 60%),
        var(--bg);
}

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: var(--sp-6) var(--sp-5);
    width: 100%;
    max-width: 26rem;
}

.brand {
    font-size: var(--text-lg);
    margin: 0 0 var(--sp-5);
    text-align: center;
    letter-spacing: -0.02em;
}

.page-title { font-size: var(--text-xl); margin: 0 0 var(--sp-3); }
.lede { margin: 0 0 var(--sp-4); color: var(--text); }
.hint { color: var(--text-muted); font-size: var(--text-sm); margin: var(--sp-4) 0 0; }

/* -------------------------------------------------------------------------
   3. FORMS
   ------------------------------------------------------------------------- */

.stack { display: flex; flex-direction: column; gap: var(--sp-3); }

label { font-size: var(--text-sm); font-weight: 600; }

input[type="email"], input[type="text"], input[type="password"],
input[type="date"], input[type="time"], input[type="number"],
select, textarea {
    width: 100%;
    padding: 0.7rem 0.8rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    /* 16px minimum, or iOS Safari zooms the whole page on focus. */
    font-size: 16px;
    font-family: inherit;
    transition: border-color .15s ease, box-shadow .15s ease;
}

input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--accent);
    /* A ring rather than an outline so it follows the rounded corner. */
    box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 25%, transparent);
}

/* Keyboard users still get a visible outline everywhere else. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

textarea { resize: vertical; min-height: 5rem; }

.field { display: flex; flex-direction: column; gap: var(--sp-1); }
.field-hint { color: var(--text-muted); font-size: var(--text-sm); margin: 0; }
.field-pair { flex-direction: row; gap: var(--sp-3); }
.field-pair > div { flex: 1; display: flex; flex-direction: column; gap: var(--sp-1); }
.form-wide { gap: var(--sp-5); }

fieldset.field {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--sp-3) var(--sp-4) var(--sp-4);
    margin: 0;
    background: var(--surface);
}

legend { font-size: var(--text-sm); font-weight: 650; padding: 0 var(--sp-2); }

/* Whole-row hit target. A 16px checkbox is a miserable thing to hit with a
   thumb, so the label carries the tap and the control rides along. */
.choice {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: 0.6rem var(--sp-1);
    font-weight: 400;
    cursor: pointer;
    min-height: 44px;
    border-radius: var(--radius-sm);
    transition: background .12s ease;
}

.choice:hover { background: var(--surface-2); }
.choice input { width: 20px; height: 20px; margin: 0; flex: none; accent-color: var(--accent); }

/* :has() — the row lights up when its control is checked, with no JS and no
   class toggling. Browsers without it simply do not highlight. */
.choice:has(input:checked) {
    background: var(--accent-soft);
    font-weight: 550;
}

/* -------------------------------------------------------------------------
   4. BUTTONS
   ------------------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    padding: 0.7rem 1.15rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-size: var(--text-base);
    font-weight: 600;
    font-family: inherit;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    /* 44px is Apple's minimum comfortable touch target and roughly matches
       Android's 48dp. Below it, people miss. */
    min-height: 44px;
    transition: background .15s ease, transform .08s ease, box-shadow .15s ease;
}

/* A small press response. It is the only thing that makes a tap feel
   acknowledged before the page navigates. */
.btn:active { transform: translateY(1px) scale(0.995); }

.btn-primary {
    background: var(--accent);
    color: var(--accent-text);
    box-shadow: var(--shadow);
}

.btn-primary:hover { background: var(--accent-hover); }

.btn-secondary {
    background: var(--surface);
    color: var(--text);
    border-color: var(--border-strong);
}

.btn-secondary:hover { background: var(--surface-2); }

.btn-danger { background: var(--bad); color: #fff; border-color: transparent; }
.btn-block { display: flex; width: 100%; }

.inline-form { display: inline; }

/* A submit button that reads as a link. Sign-out must be a POST — a GET that
   ends your session can be triggered by any <img> on any page — but it should
   not look like a primary action. */
.linkish {
    background: none;
    border: 0;
    padding: 0;
    color: var(--accent);
    font: inherit;
    font-size: var(--text-sm);
    cursor: pointer;
}

.linkish:hover { text-decoration: underline; }

/* -------------------------------------------------------------------------
   5. APP CHROME

   Two navigations, one markup. On a phone the primary destinations sit in a
   bottom bar within thumb reach, which is what every native app does and what
   this becomes once installed to the home screen. On a wider screen that bar
   would be absurd, so it moves to the top.
   ------------------------------------------------------------------------- */

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    background: color-mix(in oklch, var(--surface) 85%, transparent);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 20;
    backdrop-filter: saturate(1.6) blur(10px);
}

.topbar-brand {
    font-weight: 700;
    font-size: var(--text-lg);
    letter-spacing: -0.02em;
    text-decoration: none;
    color: var(--text);
}

.topbar-nav {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    font-size: var(--text-sm);
}

.topbar-nav a { color: var(--text-muted); text-decoration: none; font-weight: 550; }
.topbar-nav a:hover { color: var(--text); }

/* --- Theme toggle -------------------------------------------------------- */

.icon-btn {
    display: inline-grid;
    place-items: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 999px;
    background: none;
    color: var(--text-muted);
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.icon-btn:hover { background: var(--surface-2); color: var(--text); }
.icon-btn svg { width: 19px; height: 19px; grid-area: 1 / 1; }

/* Show the icon for what pressing it will DO, not for the current state — the
   control is an action, and a sun on a light page reads as a status label
   nobody asked for. data-effective is set by app.js. */
.icon-btn .icon-sun { display: none; }
.icon-btn[data-effective="dark"] .icon-sun { display: block; }
.icon-btn[data-effective="dark"] .icon-moon { display: none; }
.icon-btn[data-effective="light"] .icon-moon { display: block; }

/* On a phone the links move to the bottom bar; only the brand and sign-out
   stay up top. */
@media (max-width: 47.99rem) {
    .topbar-nav a { display: none; }
}

.content {
    max-width: 42rem;
    margin: 0 auto;
    padding: var(--sp-5) var(--sp-4) var(--sp-7);
}

/* The report is the one screen that is genuinely desktop-first — nobody
   builds a quarterly summary for an executive on a phone. */
.content-wide { max-width: 72rem; }

.section-title {
    font-size: var(--text-sm);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    margin: var(--sp-6) 0 var(--sp-3);
    font-weight: 650;
}

/* --- Bottom navigation, phones only -------------------------------------- */

.tabbar {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 30;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    background: color-mix(in oklch, var(--surface) 92%, transparent);
    backdrop-filter: saturate(1.6) blur(12px);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom);
}

.tabbar a {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 0.55rem 0 0.5rem;
    min-height: 56px;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--text-muted);
    text-decoration: none;
}

.tabbar a.is-current { color: var(--accent); }
.tabbar svg { width: 22px; height: 22px; stroke-width: 1.9; }

@media (min-width: 48rem) {
    .tabbar { display: none; }
}

/* Keeps the last element clear of the fixed bar. */
@media (max-width: 47.99rem) {
    .content { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }
}

/* -------------------------------------------------------------------------
   6. FLASH MESSAGES
   ------------------------------------------------------------------------- */

.flash {
    padding: 0.7rem 0.9rem;
    border-radius: var(--radius-sm);
    margin-bottom: var(--sp-4);
    font-size: var(--text-sm);
    border: 1px solid transparent;
    /* A coloured spine reads faster than a tinted box and survives being
       printed in black and white. */
    border-left-width: 3px;
}

.flash-success { background: var(--ok-soft); color: var(--ok); border-left-color: var(--ok); }
.flash-error { background: var(--bad-soft); color: var(--bad); border-left-color: var(--bad); }
.flash-info { background: var(--accent-soft); color: var(--accent); border-left-color: var(--accent); }
.flash-warn { background: var(--warn-soft); color: var(--warn); border-left-color: var(--warn); }

/* -------------------------------------------------------------------------
   7. TODAY — the screen that matters
   ------------------------------------------------------------------------- */

.today-date {
    color: var(--text-muted);
    margin: 0 0 var(--sp-4);
    font-size: var(--text-sm);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.today-actions { display: flex; flex-direction: column; gap: var(--sp-3); }

/* The one control that matters. Oversized on purpose: it is pressed with a
   thumb, often one-handed, often mid-stride. */
.btn-huge {
    min-height: 5.5rem;
    font-size: var(--text-lg);
    border-radius: var(--radius);
    flex-direction: column;
    gap: 2px;
    background: linear-gradient(180deg,
        color-mix(in oklch, var(--accent) 92%, white),
        var(--accent));
    box-shadow: var(--shadow-lg);
}

.btn-sub {
    display: block;
    font-size: var(--text-sm);
    font-weight: 500;
    opacity: .88;
    letter-spacing: 0.01em;
}

.today-secondary { display: flex; gap: var(--sp-3); margin-top: var(--sp-3); }
.today-secondary > * { flex: 1; }

.today-recorded {
    border: 1px solid var(--border);
    border-left: 4px solid var(--text-muted);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
    padding: var(--sp-5);
}

.today-recorded.status-in_office { border-left-color: var(--ok); }
.today-recorded.status-remote { border-left-color: var(--warn); }
.today-recorded.status-absent { border-left-color: var(--text-muted); }

.today-status { font-size: var(--text-xl); font-weight: 700; margin: 0; letter-spacing: -0.02em; }
.today-times { font-size: var(--text-lg); margin: var(--sp-1) 0 0; font-variant-numeric: tabular-nums; }
.today-times .today-note { display: inline; font-size: var(--text-sm); }
.today-note { color: var(--text-muted); font-size: var(--text-sm); margin: var(--sp-2) 0 0; }

/* --- The week strip ------------------------------------------------------ */

.week-score { font-size: var(--text-base); margin: 0 0 var(--sp-4); }
.week-score.is-met { color: var(--ok); font-weight: 600; }
.week-score.is-short { color: var(--text); }

.week-strip {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: var(--sp-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.week-day {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    padding: var(--sp-3) var(--sp-1);
    text-align: center;
    transition: border-color .15s ease;
}

.week-day-name {
    display: block;
    font-size: var(--text-xs);
    text-transform: uppercase;
    color: var(--text-muted);
    letter-spacing: 0.06em;
    font-weight: 650;
}

.week-day-mark { display: block; font-size: var(--text-xs); font-weight: 600; margin-top: var(--sp-1); }

/* Status is carried by a border AND a text label, never by colour alone — the
   strip has to be readable to someone who cannot distinguish the greens from
   the ambers, and in a screenshot pasted into a document. */
.week-day.status-in_office { border-color: var(--ok); background: var(--ok-soft); }
.week-day.status-remote { border-color: var(--warn); background: var(--warn-soft); }
.week-day.status-absent { border-color: var(--border-strong); background: var(--surface-2); }
.week-day.is-closure { opacity: .5; }
.week-day.is-today { outline: 2px solid var(--accent); outline-offset: 1px; }

/* -------------------------------------------------------------------------
   8. HISTORY
   ------------------------------------------------------------------------- */

.week, .history-week { margin: 0 0 var(--sp-6); }

.history-week-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    font-size: var(--text-base);
    margin: 0 0 var(--sp-2);
    flex-wrap: wrap;
}

.pill {
    font-size: var(--text-xs);
    font-weight: 650;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--accent-soft);
    color: var(--accent);
    white-space: nowrap;
    letter-spacing: 0.01em;
}

.pill-ok { background: var(--ok-soft); color: var(--ok); }
.pill-short { background: var(--bad-soft); color: var(--bad); }

.history-days {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    overflow: hidden;
    box-shadow: var(--shadow);
}

.history-day {
    display: grid;
    grid-template-columns: 4.5rem 1fr auto;
    align-items: baseline;
    gap: var(--sp-3);
    padding: 0.7rem var(--sp-4);
    border-bottom: 1px solid var(--border);
    font-size: var(--text-sm);
}

.history-day:last-child { border-bottom: 0; }
.history-day.is-today { background: var(--accent-soft); }
.history-day-date { color: var(--text-muted); font-size: var(--text-xs); font-weight: 650; }
.history-day-note { display: block; color: var(--text-muted); font-size: var(--text-xs); }
.history-day-action a { color: var(--accent); text-decoration: none; font-size: var(--text-sm); }
.muted { color: var(--text-muted); }
.history-exceptions { color: var(--text-muted); font-size: var(--text-sm); margin: var(--sp-2) 0 0; }

/* -------------------------------------------------------------------------
   9. REPORT
   ------------------------------------------------------------------------- */

.report-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--sp-3);
    margin: 0 0 var(--sp-4);
    padding: var(--sp-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.report-filter > div { display: flex; flex-direction: column; gap: var(--sp-1); }
.report-filter label { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
.report-filter input, .report-filter select { width: auto; min-width: 9.5rem; }

.export-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin: var(--sp-4) 0 var(--sp-5);
}

.export-label {
    font-size: var(--text-xs);
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    margin-right: var(--sp-1);
}

.export-bar .btn { padding: 0.5rem 0.95rem; min-height: 38px; font-size: var(--text-sm); }

/* A wide table scrolls inside its own box. Letting the page scroll sideways
   instead makes the whole app feel broken on a phone. */
.table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm);
    white-space: nowrap;
}

.data-table th, .data-table td { padding: 0.6rem 0.9rem; text-align: left; }

.data-table thead th {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
    /* Sticky so the columns stay labelled while scrolling a long report. */
    position: sticky;
    top: 0;
    z-index: 1;
}

.data-table tbody tr { border-bottom: 1px solid var(--border); }
.data-table tbody tr:last-child { border-bottom: 0; }
.data-table tbody tr:hover { background: var(--surface-2); }

/* Tabular figures so columns of numbers line up on the decimal. */
.data-table td.num, .data-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table a { color: var(--accent); text-decoration: none; font-weight: 550; }
.data-table tfoot td { font-weight: 700; border-top: 2px solid var(--border-strong); background: var(--surface-2); }
.data-table tr.is-inactive { opacity: .6; }

.data-table code {
    font-size: var(--text-xs);
    background: var(--surface-2);
    padding: 2px 6px;
    border-radius: 5px;
}

.methodology {
    margin: var(--sp-5) 0 0;
    padding: var(--sp-4);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.methodology summary { cursor: pointer; font-weight: 650; color: var(--text); }
.methodology p { margin: var(--sp-3) 0 0; }

/* --- Per-person blocks --------------------------------------------------- */

.person-block { margin: 0 0 var(--sp-6); }

.person-head {
    display: flex;
    align-items: baseline;
    gap: var(--sp-3);
    flex-wrap: wrap;
    font-size: var(--text-lg);
    margin: 0 0 var(--sp-2);
    padding-bottom: var(--sp-2);
    border-bottom: 2px solid var(--border);
}

.person-head .pill { margin-left: auto; }

/* -------------------------------------------------------------------------
   10. ADMIN
   ------------------------------------------------------------------------- */

.subnav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-1);
    margin: 0 0 var(--sp-5);
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
}

.subnav a {
    padding: 0.5rem 0.85rem;
    text-decoration: none;
    color: var(--text-muted);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    font-size: var(--text-sm);
    font-weight: 550;
    white-space: nowrap;
}

.subnav a:hover { color: var(--text); }
.subnav a.is-current { color: var(--accent); border-bottom-color: var(--accent); font-weight: 650; }

/* --- Teams ---------------------------------------------------------------
   Cards rather than a table. A <form> cannot span table cells, so an editable
   row either crams the whole form into one column — which is what forced a
   horizontal scroll here — or duplicates fields across cells. Neither is worth
   the alignment a table buys.
   ------------------------------------------------------------------------- */

.team-list { list-style: none; margin: 0 0 var(--sp-4); padding: 0; display: grid; gap: var(--sp-3); }

.team-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: var(--sp-4);
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--sp-3);
}

.team-form {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--sp-3);
    flex: 1 1 20rem;
    margin: 0;
}

.team-field { display: flex; flex-direction: column; gap: var(--sp-1); flex: 1 1 10rem; min-width: 0; }

/* The name gets the extra room when there is any, and shrinks first when there
   is not — min-width:0 is what actually lets a flex item shrink below the
   intrinsic width of its input. */
.team-field-name { flex: 2 1 12rem; }

.team-field label {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
}

.team-field input, .team-field select { width: 100%; min-width: 0; }
.team-meta { display: flex; align-items: center; padding-bottom: 0.55rem; }
.team-actions { padding-bottom: 0; }
.team-delete { margin-left: auto; align-self: center; }

@media (max-width: 34rem) {
    .team-card { flex-direction: column; align-items: stretch; }
    .team-form { flex-direction: column; align-items: stretch; }
    .team-delete { margin-left: 0; align-self: flex-start; }
}

.row-actions { display: flex; gap: var(--sp-4); align-items: baseline; white-space: nowrap; }
.row-actions a { color: var(--accent); text-decoration: none; font-size: var(--text-sm); }

.audit-meta {
    white-space: normal;
    max-width: 28rem;
    font-size: var(--text-xs);
    color: var(--text-muted);
    word-break: break-word;
}

/* --- Destructive actions ------------------------------------------------- */

/* Visually separated and at the bottom, so it is never adjacent to a control
   someone reaches for routinely. */
.danger-zone {
    margin: var(--sp-7) 0 0;
    padding: var(--sp-4);
    border: 1px solid var(--bad);
    border-radius: var(--radius);
    background: var(--bad-soft);
}

.danger-zone .section-title { margin-top: 0; color: var(--bad); }
.danger-zone .hint { color: var(--text); }
.danger-link { color: var(--bad); font-weight: 650; }

/* A URL or password that must be selectable and readable in full — never
   truncated, since half a credential is indistinguishable from a wrong one. */
.link-box {
    background: var(--surface-2);
    border: 1px solid var(--accent);
    border-radius: var(--radius-sm);
    padding: var(--sp-3);
    font-size: var(--text-sm);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-all;
    user-select: all;
    margin: 0;
}

/* -------------------------------------------------------------------------
   11. CONTAINER QUERIES

   The report renders inside two very different widths — the narrow content
   column and the wide one. A container query lets the table respond to the
   space it actually has rather than to the viewport, which is the difference
   between correct on a laptop and correct in a sidebar.
   ------------------------------------------------------------------------- */

@supports (container-type: inline-size) {
    .content { container-type: inline-size; container-name: page; }

    @container page (max-width: 34rem) {
        .data-table th, .data-table td { padding: 0.5rem 0.6rem; }
        .person-head { font-size: var(--text-base); }
    }
}

/* -------------------------------------------------------------------------
   12. PRINT

   Reports get printed and photocopied. Chrome, colour and interaction go.
   ------------------------------------------------------------------------- */

@media print {
    .topbar, .tabbar, .export-bar, .report-filter, .danger-zone, .btn { display: none !important; }
    body { background: #fff; color: #000; }
    .content, .content-wide { max-width: none; padding: 0; }
    .table-scroll { overflow: visible; border: 0; box-shadow: none; }
    .data-table { white-space: normal; font-size: 10pt; }
    .data-table thead { display: table-header-group; }
    .person-block { page-break-inside: avoid; }
}
