/* R.D.M Portal - brand system
   Forest #2D5520 | Sage #72BD74 (logo mark only) | Pale #EAF2E7 / #D7E5D4
   Status: red #CC0000 | orange #B85C00 | green #3C7A33
   Font: Assistant (self-hosted woff2, added via GitHub web UI) */

@font-face {
    font-family: 'Assistant';
    src: url('/assets/fonts/assistant-400.woff2') format('woff2');
    font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
    font-family: 'Assistant';
    src: url('/assets/fonts/assistant-600.woff2') format('woff2');
    font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
    font-family: 'Assistant';
    src: url('/assets/fonts/assistant-700.woff2') format('woff2');
    font-weight: 700; font-style: normal; font-display: swap;
}

:root {
    --forest: #2D5520;
    --forest-dark: #214017;
    --sage: #72BD74;
    --pale: #EAF2E7;
    --pale-2: #D7E5D4;
    --ink: #1E2A1B;
    --muted: #5C6B58;
    --line: #C3D4BF;
    --white: #FFFFFF;
    --st-red: #CC0000;
    --st-orange: #B85C00;
    --st-green: #3C7A33;
    --radius: 10px;
    --shadow: 0 2px 14px rgba(45, 85, 32, 0.10);

    /* Note category palette (note_colors() in helpers.php). Brand colours
       first, then ten more distinct hues for teams with many categories. */
    --nc-green:  #3C7A33;
    --nc-sage:   #72BD74;
    --nc-forest: #2D5520;
    --nc-olive:  #7A8A2E;
    --nc-teal:   #1C8C8C;
    --nc-sky:    #4A9BD5;
    --nc-blue:   #1F5FA8;
    --nc-navy:   #1E3A5F;
    --nc-purple: #6B3FA0;
    --nc-pink:   #C2418A;
    --nc-red:    #CC0000;
    --nc-orange: #B85C00;
    --nc-gold:   #B08A1E;
    --nc-brown:  #8B5A2B;
    --nc-gray:   #8A8A8A;
    --nc-black:  #1E2A1B;
}

* { box-sizing: border-box; }

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

body {
    margin: 0;
    font-family: 'Assistant', -apple-system, 'Segoe UI', Arial, sans-serif;
    font-size: 16px;
    line-height: 1.55;
    color: var(--ink);
    background: var(--pale);
    direction: rtl;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

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

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

/* ---- Top bar ---- */
.topbar {
    background: var(--white);
    border-bottom: 1px solid var(--line);
}
.topbar-inner {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 20px;
    height: 60px;
    display: flex;
    align-items: center;
    gap: 28px;
}
.wordmark {
    font-weight: 700;
    font-size: 1.15rem;
    color: var(--forest);
    text-decoration: none;
    letter-spacing: 0.02em;
}
.wordmark span { font-weight: 400; color: var(--muted); }
.wordmark-large {
    font-weight: 700;
    font-size: 1.7rem;
    color: var(--forest);
    letter-spacing: 0.04em;
}
.topnav { display: flex; gap: 18px; flex: 1; flex-wrap: wrap; }
.topnav a {
    text-decoration: none;
    color: var(--ink);
    font-weight: 600;
    padding: 6px 2px;
    border-bottom: 2px solid transparent;
}
.topnav a:hover { border-bottom-color: var(--sage); }
.topbar-user { display: flex; align-items: center; gap: 14px; }
.user-name { color: var(--muted); font-size: 0.95rem; text-decoration: none; }
.user-name:hover { color: var(--forest); }

/* ---- Layout ---- */
.app-main { max-width: 1100px; margin: 0 auto; padding: 28px 20px 60px; width: 100%; flex: 1; }
.auth-main {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px 16px;
}

.page-head h1 { font-size: 1.5rem; margin: 0 0 10px; color: var(--forest-dark); }
.page-head { margin-bottom: 18px; }
.tmeta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    margin-bottom: 6px;
}

/* ---- Footer ---- */
.app-foot {
    text-align: center;
    padding: 14px 20px 20px;
    color: var(--muted);
    font-size: 0.85rem;
}
.app-foot a { color: var(--muted); }
.app-foot a:hover { color: var(--forest); }
.app-foot span { margin: 0 6px; }

/* ---- Auth card ---- */
.auth-card {
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    width: 100%;
    max-width: 400px;
    padding: 34px 30px 28px;
}
.auth-brand { text-align: center; margin-bottom: 22px; }
.auth-sub { color: var(--muted); margin-top: 2px; }
.auth-links { text-align: center; margin: 18px 0 0; font-size: 0.95rem; }

/* ---- Forms ---- */
label { display: block; font-weight: 600; margin: 14px 0 5px; }
input[type="email"], input[type="password"], input[type="text"],
input[type="number"], input[type="date"], input[type="time"],
input[type="month"], input[type="file"],
select, textarea {
    width: 100%;
    padding: 11px 12px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--white);
    font: inherit;
    color: var(--ink);
}
input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--forest);
    box-shadow: 0 0 0 3px rgba(45, 85, 32, 0.15);
}
.check {
    display: flex; align-items: center; gap: 8px;
    font-weight: 400; margin: 8px 0 4px; cursor: pointer;
}
.check input { width: auto; }
.checks { margin: 10px 0; }
.radios { display: flex; gap: 22px; flex-wrap: wrap; margin: 8px 0; }
.code-input {
    text-align: center;
    letter-spacing: 0.5em;
    font-size: 1.3rem;
    direction: ltr;
}

/* One-line filter bar: selects share the row and wrap on narrow screens,
   the buttons sit at the end of the same line. Labels are visually hidden
   (.sr-only); the placeholder option carries the field name instead. */
.filter-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.filter-row select,
.filter-row input[type="text"] {
    flex: 1 1 150px;
    width: auto;
    min-width: 0;
    padding: 9px 10px;
}
.filter-row .btn { flex: 0 0 auto; }

/* ---- Buttons ---- */
.btn {
    display: inline-block;
    border: none;
    border-radius: 8px;
    padding: 11px 20px;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    text-align: center;
}
.btn-primary { background: var(--forest); color: var(--white); }
.btn-primary:hover { background: var(--forest-dark); }
.btn-ghost {
    background: transparent;
    color: var(--forest);
    border: 1px solid var(--line);
    padding: 7px 14px;
}
.btn-ghost:hover { background: var(--pale); }
.btn-block { width: 100%; margin-top: 18px; }

/* ---- Floating action button + dialog ----
   The board's "new task" lives behind a round + fixed to the end corner
   (bottom-left in RTL), one click from anywhere on the page. The form opens
   in a native <dialog>; the card padding lives on .modal-body so a click
   that reaches the dialog element itself is a backdrop click. */
.fab {
    position: fixed;
    bottom: calc(24px + env(safe-area-inset-bottom, 0px));
    inset-inline-end: 24px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: none;
    background: var(--forest);
    color: var(--white);
    box-shadow: 0 6px 18px rgba(45, 85, 32, 0.35);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 30;
    padding: 0;
}
.fab:hover { background: var(--forest-dark); }
.fab svg { display: block; }

dialog.modal {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 0;
    width: min(92vw, 680px);
    max-height: min(90dvh, 100%);
    background: var(--white);
    color: var(--ink);
    box-shadow: 0 12px 40px rgba(30, 42, 27, 0.25);
}
dialog.modal::backdrop { background: rgba(30, 42, 27, 0.45); }
.modal-body { padding: 20px 24px 24px; }
.modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 4px;
}
.modal-head .panel-title { margin: 0; }
.modal-head form { margin: 0; }

/* ---- Notices ---- */
.notice {
    border-radius: 8px;
    padding: 11px 14px;
    margin: 0 0 14px;
    font-size: 0.95rem;
    border: 1px solid;
}
.notice-error   { background: #FBEFEF; border-color: #E4B8B8; color: var(--st-red); }
.notice-success { background: var(--pale);  border-color: var(--line); color: var(--st-green); }
.notice-info    { background: #F3F1E7; border-color: #DDD6B8; color: var(--st-orange); }

/* ---- Empty states ---- */
.empty-state {
    background: var(--white);
    border: 1px dashed var(--line);
    border-radius: var(--radius);
    padding: 42px 24px;
    text-align: center;
    color: var(--muted);
}

/* ---- Panels & grids ---- */
.panel {
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 18px 20px;
    margin-bottom: 18px;
}
.panel-title { font-size: 1.05rem; margin: 0 0 12px; color: var(--forest-dark); }
.panel-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 12px; flex-wrap: wrap; }
.panel-row .panel-title { margin: 0; }
.panel-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: 0 16px; }
.newform > summary { cursor: pointer; font-weight: 600; color: var(--forest); }
.mt { margin-top: 12px; }
.muted { color: var(--muted); }
.prewrap { white-space: pre-wrap; margin: 0; overflow-wrap: anywhere; }

/* ---- Table scroll wrapper: tables render inside a horizontal scroller
       so wide tables never break the page width on narrow screens. ---- */
.table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
}

/* ---- Board split: board 2/3 + overview 1/3 on landscape screens.
       Portrait keeps the single-column board only (no fixed pixel breakpoints,
       widths derive from the viewport and relative units). ---- */
.app-main:has(.board-layout) { max-width: min(96vw, 90rem); }
.board-layout {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(17rem, 1fr);
    gap: 1.25rem;
    align-items: start;
}
.board-main { min-width: 0; }
.board-side {
    position: sticky;
    top: 1rem;
    max-height: calc(100dvh - 2rem);
    overflow-y: auto;
    padding-left: 0.3rem;
    scrollbar-width: thin;
    scrollbar-color: var(--line) transparent;
}
.board-side::-webkit-scrollbar { width: 0.45rem; }
.board-side::-webkit-scrollbar-track { background: transparent; }
.board-side::-webkit-scrollbar-thumb {
    background: var(--line);
    border-radius: 1rem;
}
.board-side::-webkit-scrollbar-thumb:hover { background: var(--sage); }
.side-panel { padding: 0.9rem 1.1rem; margin-bottom: 0.9rem; }
.side-flags { display: flex; gap: 0.75rem; }
.side-flag { flex: 1; text-align: center; }
.flag-num { display: block; font-size: 1.5rem; font-weight: 700; color: var(--forest-dark); line-height: 1.2; }
.flag-red .flag-num { color: var(--st-red); }
.flag-orange .flag-num { color: var(--st-orange); }
.flag-label { font-size: 0.82rem; color: var(--muted); }
.side-client { border-top: 1px solid var(--line); padding: 0.75rem 0; }
.side-client:first-of-type { border-top: none; padding-top: 0; }
.side-client-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 0.6rem; justify-content: space-between; }
.side-client-name { font-weight: 700; text-decoration: none; }
.side-client-name:hover { text-decoration: underline; }
.side-counts { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.side-count {
    font-size: 0.76rem;
    color: var(--muted);
    background: var(--pale);
    border-radius: 1rem;
    padding: 0.05rem 0.55rem;
    white-space: nowrap;
}
.side-count b { color: var(--forest-dark); }
.side-count-active { background: var(--pale-2); }
.side-tasks { display: flex; flex-direction: column; gap: 0.3rem; margin: 0.45rem 0 0.35rem; }
.side-task {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--pale);
    border: 1px solid transparent;
    border-radius: 0.5rem;
    padding: 0.35rem 0.6rem;
    font-size: 0.9rem;
    text-decoration: none;
    color: var(--ink);
}
.side-task:hover { border-color: var(--line); background: var(--white); }
.side-task .pdot { width: 0.55rem; height: 0.55rem; flex: 0 0 0.55rem; }
.side-task-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
}
.side-task:hover .side-task-title { color: var(--forest); }
.side-task-status { font-size: 0.74rem; white-space: nowrap; color: var(--muted); }
.side-task-status.sts-in_progress { color: var(--st-green); font-weight: 600; }
.side-task-status.sts-waiting { color: var(--st-orange); }
.side-meta { font-size: 0.85rem; }
.age-warn { color: var(--st-orange); font-weight: 600; }
.meter-sm { height: 0.5rem; margin-top: 0.4rem; }
.side-old { padding: 0.45rem 0; border-top: 1px solid var(--line); font-size: 0.92rem; }
.side-old:first-of-type { border-top: none; padding-top: 0; }
.side-old a { text-decoration: none; color: var(--ink); font-weight: 600; display: block; }
.side-old a:hover { color: var(--forest); }
.side-note { font-size: 0.82rem; margin-top: 0.2rem; }

/* Pinned notes in the board's side panel: each is one link to where the
   note lives, on the same paper tint as the note cards, category colour on
   the start edge, body clamped to three lines. */
.snote {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    background: #FFF9E6;
    border: 1px solid #E8DCA8;
    border-right: 4px solid var(--line);
    border-radius: 0.5rem;
    padding: 0.5rem 0.7rem;
    margin-bottom: 0.5rem;
    text-decoration: none;
    color: var(--ink);
    font-size: 0.9rem;
}
.snote:hover { border-color: var(--forest); }
.snote-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; flex-wrap: wrap; }
.snote-head b { color: var(--forest-dark); }
.snote-title { font-weight: 600; overflow-wrap: anywhere; }
.snote-body {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    color: var(--muted);
}

@media (orientation: portrait) {
    .app-main:has(.board-layout) { max-width: 68.75rem; }
    .board-layout { display: block; }
    .board-side { display: none; }
}

/* ---- Task list (grouped by status, replaced kanban) ---- */
.tlist { display: flex; flex-direction: column; gap: 10px; }
.tgroup {
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
}
.tgroup > summary {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: var(--pale-2);
    font-weight: 600;
    color: var(--forest-dark);
    list-style: none;
    min-height: 44px;
}
.tgroup > summary::-webkit-details-marker { display: none; }
.tgroup > summary::before { content: '\25C2'; color: var(--muted); font-size: 0.8em; }
.tgroup[open] > summary::before { content: '\25BE'; }
.tgroup-empty > summary { background: var(--white); color: var(--muted); font-weight: 400; }
.tgroup.drag-over { outline: 2px dashed var(--forest); outline-offset: -2px; }
.tgroup-none { margin: 0; padding: 10px 16px; border-top: 1px solid var(--line); font-size: 0.9rem; }
.count { color: var(--muted); font-weight: 400; font-size: 0.85rem; }
.trow {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 16px;
    border-top: 1px solid var(--line);
    cursor: grab;
}
.trow:hover { background: var(--pale); }
.trow.dragging { opacity: 0.45; }

/* Insertion slot shown while dragging: a bar with a dot at its start,
   inserted between rows so a real gap opens where the task will land. */
.drop-marker {
    height: 4px;
    background: var(--forest);
    border-radius: 2px;
    margin: 4px 12px;
    position: relative;
    pointer-events: none;
}
.drop-marker::before {
    content: '';
    position: absolute;
    top: -3px;
    right: -6px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--forest);
}
.trow-title {
    flex: 1;
    min-width: 200px;
    text-decoration: none;
    color: var(--ink);
    font-weight: 600;
}
.trow-title:hover { color: var(--forest); }
.trow-meta { font-size: 0.88rem; white-space: nowrap; }
.trow-date { font-size: 0.88rem; color: var(--muted); min-width: 72px; text-align: left; }
.pdot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex: 0 0 10px;
    background: var(--line);
}
.pdot-urgent { background: var(--st-red); }
.pdot-high { background: var(--st-orange); }
.pdot-low { background: var(--pale-2); border: 1px solid var(--line); }
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}
.board-hint { font-size: 0.88rem; margin-top: 10px; }
.overdue { color: var(--st-red); font-weight: 600; }

/* ---- Work clock (/team/hours) ----
   The status panel is the whole screen's answer to "am I on the clock".
   The journal reuses the task-group pattern: a day is a collapsible group,
   a shift inside it opens into its own edit form. */
.clock { text-align: center; padding: 24px 20px 26px; }
.clock-state { color: var(--muted); margin: 0; }
.clock-state strong { color: var(--ink); }
.clock-time {
    font-size: 2.6rem;
    font-weight: 700;
    line-height: 1.15;
    color: var(--forest-dark);
    font-variant-numeric: tabular-nums;
    margin: 4px 0 0;
}
.clock-running .clock-time { color: var(--st-green); }
.clock-sub { color: var(--muted); font-size: 0.92rem; margin: 2px 0 18px; }
.clock-btn { min-width: 15rem; font-size: 1.05rem; padding: 14px 28px; }

.days { display: flex; flex-direction: column; gap: 10px; }
.day {
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
}
.day > summary {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: var(--pale-2);
    font-weight: 600;
    color: var(--forest-dark);
    list-style: none;
    min-height: 44px;
}
.day > summary::-webkit-details-marker { display: none; }
.day > summary::before { content: '\25C2'; color: var(--muted); font-size: 0.8em; }
.day[open] > summary::before { content: '\25BE'; }
.day-count { color: var(--muted); font-weight: 400; font-size: 0.85rem; }
.day-total { margin-inline-start: auto; font-variant-numeric: tabular-nums; }
.day-split {
    color: var(--muted);
    font-weight: 400;
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
}
.day-split.day-ot { color: var(--st-orange); font-weight: 600; }

.shift { border-top: 1px solid var(--line); }
.shift > summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 14px;
    padding: 10px 16px;
    min-height: 44px;
}
.shift > summary::-webkit-details-marker { display: none; }
.shift > summary:hover { background: var(--pale); }
.shift[open] > summary { background: var(--pale); }
.shift-time { font-weight: 600; font-variant-numeric: tabular-nums; min-width: 8.5rem; }
.shift-len { color: var(--muted); font-variant-numeric: tabular-nums; }
.shift-live { color: var(--st-green); font-weight: 600; }
.shift-note { color: var(--muted); font-size: 0.9rem; overflow-wrap: anywhere; }
.shift-edit { margin-inline-start: auto; color: var(--forest); font-size: 0.88rem; font-weight: 600; }
.shift-form { padding: 2px 16px 16px; background: var(--pale); }
.shift-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }

/* ---- Chips ---- */
.chip {
    display: inline-block;
    padding: 2px 9px;
    border-radius: 20px;
    font-size: 0.78rem;
    font-weight: 600;
    background: var(--pale);
    color: var(--forest-dark);
    text-decoration: none;
}
.chip-client {
    background: var(--forest);
    color: var(--white);
    border: 1px solid var(--forest);
}
.chip-client:hover { background: var(--forest-dark); }
.chip-bug            { background: #FBEFEF; color: var(--st-red); }
.chip-question       { background: var(--pale); color: var(--st-green); }
.chip-change_request { background: #F3F1E7; color: var(--st-orange); }
.chip-internal       { background: #EAEAEA; color: #555; }
.chip-p-urgent { background: var(--st-red); color: var(--white); }
.chip-p-high   { background: #FBEFEF; color: var(--st-red); }
.chip-p-low    { background: #EAEAEA; color: var(--muted); }
.chip-appr-pending           { background: #F3F1E7; color: var(--st-orange); }
.chip-appr-approved          { background: var(--pale); color: var(--st-green); }
.chip-appr-changes_requested { background: #FBEFEF; color: var(--st-red); }
.chip-appr-superseded        { background: #EAEAEA; color: var(--muted); }
.chip-appr-cancelled         { background: #EAEAEA; color: var(--muted); }

/* ---- Tables ---- */
.table {
    width: 100%;
    border-collapse: collapse;
    background: var(--white);
    font-size: 0.95rem;
}
.table th {
    background: var(--pale-2);
    text-align: right;
    padding: 10px 12px;
    color: var(--forest-dark);
}
.table td { padding: 10px 12px; border-top: 1px solid var(--line); }

/* ---- Ticket thread ---- */
.msg {
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 12px 14px;
    margin-bottom: 10px;
}
.msg-internal { background: #FFF9E6; border-color: #E8DCA8; }
.msg-head {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    color: var(--muted);
    font-size: 0.85rem;
    margin-bottom: 6px;
}
.msg-head strong { color: var(--ink); }
.filelist { margin: 0; padding-right: 18px; }
.filelist li { margin-bottom: 6px; overflow-wrap: anywhere; }

/* ---- Approvals ---- */
.approval-row {
    border-top: 1px solid var(--line);
    padding: 12px 0;
}
.approval-row:first-of-type { border-top: none; padding-top: 0; }
.appr-meta { font-size: 0.88rem; margin-top: 2px; }
.decision-note {
    background: var(--pale);
    border-right: 3px solid var(--forest);
    border-radius: 6px;
    padding: 10px 12px;
    margin-top: 8px;
    font-size: 0.95rem;
}
.approval-actions { display: flex; gap: 12px; flex-wrap: wrap; }

/* ---- Retainer meter ---- */
.meter-row {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 0.95rem;
    margin-bottom: 8px;
}
.meter {
    background: var(--pale-2);
    border-radius: 20px;
    height: 14px;
    overflow: hidden;
}
.meter-fill {
    height: 100%;
    background: var(--st-green);
    border-radius: 20px;
}
.meter-fill.warn { background: var(--st-orange); }
.meter-fill.over { background: var(--st-red); }

/* ---- Users ---- */
.userrow {
    border-top: 1px solid var(--line);
    padding: 10px 0;
}
.userrow:first-of-type { border-top: none; }
.userrow > summary {
    cursor: pointer;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
}

/* ---- Team notes (about a client or internal) ----
   A card grid on the same paper tint as internal ticket messages, so
   "internal" reads the same way across the portal. The start edge (right,
   in RTL) takes the category's colour key (note_colors() in helpers.php,
   --nc-* above); pinned notes get a forest frame and come first (ordering
   is done server-side). The same cards, compact, sit above the board when
   it is filtered to one client. */
.notes-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
    gap: 12px;
}
.note {
    background: #FFF9E6;
    border: 1px solid #E8DCA8;
    border-right: 4px solid var(--line);
    border-radius: 8px;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}
.note-pinned { border-color: var(--forest); box-shadow: var(--shadow); }
.note-c-green  { border-right-color: var(--nc-green); }
.note-c-sage   { border-right-color: var(--nc-sage); }
.note-c-forest { border-right-color: var(--nc-forest); }
.note-c-olive  { border-right-color: var(--nc-olive); }
.note-c-teal   { border-right-color: var(--nc-teal); }
.note-c-sky    { border-right-color: var(--nc-sky); }
.note-c-blue   { border-right-color: var(--nc-blue); }
.note-c-navy   { border-right-color: var(--nc-navy); }
.note-c-purple { border-right-color: var(--nc-purple); }
.note-c-pink   { border-right-color: var(--nc-pink); }
.note-c-red    { border-right-color: var(--nc-red); }
.note-c-orange { border-right-color: var(--nc-orange); }
.note-c-gold   { border-right-color: var(--nc-gold); }
.note-c-brown  { border-right-color: var(--nc-brown); }
.note-c-gray   { border-right-color: var(--nc-gray); }
.note-c-black  { border-right-color: var(--nc-black); }
.note-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Category chips: a light tint of the colour behind text in the colour
   itself; forest, navy and black are dark enough to read white on solid. */
.chip-note-c-green  { background: #E6F0E4; color: var(--nc-green); }
.chip-note-c-sage   { background: #E4F3E5; color: #3F7A41; }
.chip-note-c-forest { background: var(--nc-forest); color: var(--white); }
.chip-note-c-olive  { background: #EFF2E0; color: var(--nc-olive); }
.chip-note-c-teal   { background: #E1F2F2; color: var(--nc-teal); }
.chip-note-c-sky    { background: #E6F2FA; color: #2F7BB5; }
.chip-note-c-blue   { background: #E5ECF7; color: var(--nc-blue); }
.chip-note-c-navy   { background: var(--nc-navy); color: var(--white); }
.chip-note-c-purple { background: #EDE7F5; color: var(--nc-purple); }
.chip-note-c-pink   { background: #F8E6F0; color: var(--nc-pink); }
.chip-note-c-red    { background: #FBEFEF; color: var(--nc-red); }
.chip-note-c-orange { background: #F3F1E7; color: var(--nc-orange); }
.chip-note-c-gold   { background: #F7F1DD; color: #8C6C12; }
.chip-note-c-brown  { background: #F1E9E1; color: var(--nc-brown); }
.chip-note-c-gray   { background: #EAEAEA; color: #555; }
.chip-note-c-black  { background: var(--nc-black); color: var(--white); }
.note-pin-chip { background: var(--forest); color: var(--white); }
.note-title { font-size: 1rem; margin: 0; color: var(--forest-dark); overflow-wrap: anywhere; }
.note-body { font-size: 0.95rem; flex: 1; }
.note-compact .note-body {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.note-foot { font-size: 0.82rem; }
.note-edit > summary {
    cursor: pointer;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--forest);
}
.note-edit label { margin-top: 8px; }
.note-edit textarea { min-height: 6rem; }
.note-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }

/* Colour picker for note categories: one radio per palette key, drawn as a
   circle of that colour; the checked one gets a forest ring. Same keys as
   .note-c-* / .chip-note-c-*. A bare .swatch-dot (no input) is just a dot. */
.swatches { display: flex; gap: 10px; flex-wrap: wrap; margin: 4px 0 6px; }
.swatch { position: relative; display: inline-flex; margin: 0; cursor: pointer; }
.swatch input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.swatch-dot {
    display: inline-block;
    width: 28px;
    height: 28px;
    flex: 0 0 28px;
    border-radius: 50%;
    border: 2px solid var(--white);
    box-shadow: 0 0 0 1px var(--line);
    background: var(--nc-gray);
}
.swatch input:checked + .swatch-dot { box-shadow: 0 0 0 3px var(--forest); }
.swatch input:focus-visible + .swatch-dot { outline: 3px solid var(--forest); outline-offset: 3px; }
.swatch-green  { background: var(--nc-green); }
.swatch-sage   { background: var(--nc-sage); }
.swatch-forest { background: var(--nc-forest); }
.swatch-olive  { background: var(--nc-olive); }
.swatch-teal   { background: var(--nc-teal); }
.swatch-sky    { background: var(--nc-sky); }
.swatch-blue   { background: var(--nc-blue); }
.swatch-navy   { background: var(--nc-navy); }
.swatch-purple { background: var(--nc-purple); }
.swatch-pink   { background: var(--nc-pink); }
.swatch-red    { background: var(--nc-red); }
.swatch-orange { background: var(--nc-orange); }
.swatch-gold   { background: var(--nc-gold); }
.swatch-brown  { background: var(--nc-brown); }
.swatch-gray   { background: var(--nc-gray); }
.swatch-black  { background: var(--nc-black); }
summary > .swatch-dot { width: 16px; height: 16px; flex-basis: 16px; }

/* ---- Client dashboard ---- */
.cards-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 18px; }
.stat-card {
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 18px 14px;
    text-align: center;
}
.stat-attention { border-color: var(--st-orange); }
.stat-num { font-size: 1.9rem; font-weight: 700; color: var(--forest-dark); }
.stat-label { color: var(--muted); font-size: 0.92rem; }

/* ---- 2FA setup ---- */
.steps { padding-right: 20px; }
.steps li { margin-bottom: 6px; }
.qr-wrap { text-align: center; margin: 18px 0; }
.qr-wrap #qr { display: inline-block; padding: 12px; background: var(--white); }
.secret {
    font-family: 'Courier New', monospace;
    direction: ltr;
    font-size: 1.05rem;
    letter-spacing: 0.06em;
    background: var(--pale);
    display: inline-block;
    padding: 6px 12px;
    border-radius: 8px;
}

@media (max-width: 900px) {
    .grid-2 { grid-template-columns: 1fr; }
    .cards-4 { grid-template-columns: repeat(2, 1fr); }
}

/* ---- Mobile pass (<=640px) ----
   Top bar wraps to two rows: wordmark + logout on the first row, the nav
   becomes a full-width horizontally-scrollable strip on the second row
   (no wrapping, no hidden links). Touch targets grow to 44px minimum,
   dense grids collapse to a single column, and wide tables scroll
   sideways instead of stretching the page. */
@media (max-width: 640px) {
    .topbar {
        position: sticky;
        top: 0;
        z-index: 20;
    }
    .topbar-inner {
        height: auto;
        min-height: 54px;
        flex-wrap: wrap;
        gap: 0 12px;
        padding: 8px 14px 0;
    }
    .topbar-user { margin-inline-start: auto; }
    .user-name { display: none; }
    .btn-ghost { padding: 8px 14px; }
    .topnav {
        order: 3;
        flex: 1 1 100%;
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        gap: 4px;
        margin: 2px -14px 0;
        padding: 0 14px;
        scrollbar-width: none;
    }
    .topnav::-webkit-scrollbar { display: none; }
    .topnav a {
        white-space: nowrap;
        padding: 10px 8px;
        border-bottom-width: 3px;
    }

    .app-main { padding: 18px 14px 96px; }
    .page-head h1 { font-size: 1.28rem; }
    .panel { padding: 14px; }
    .auth-card { padding: 26px 20px 22px; }

    /* Forms: single column, stacked radios, full-width primary actions. */
    .form-grid { grid-template-columns: 1fr; gap: 0; }
    .radios { flex-direction: column; gap: 6px; }
    .grid-2 { gap: 14px; }
    .panel form .btn-primary,
    .panel form .btn-block { width: 100%; }
    .btn { min-height: 44px; }
    .approval-actions .btn { flex: 1 1 auto; }

    /* Filter bar keeps its row: two fields per line, buttons share a line. */
    .filter-row select,
    .filter-row input[type="text"] { flex-basis: calc(50% - 4px); }
    .panel form.filter-row .btn { flex: 1 1 auto; width: auto; }

    /* Floating + and dialog: a little closer to the edge, dialog nearly full width. */
    .fab { inset-inline-end: 16px; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
    dialog.modal { width: 96vw; }
    .modal-body { padding: 16px 14px 18px; }
    .modal-body .btn-primary { width: 100%; }

    /* Tables: sideways scroll instead of breaking the layout. */
    .table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        max-width: 100%;
    }
    .table th, .table td { white-space: nowrap; }

    /* Task rows: title on its own line, meta wraps beneath. */
    .trow { flex-wrap: wrap; row-gap: 2px; padding: 10px 14px; }
    .trow-title { flex: 1 1 calc(100% - 30px); min-width: 0; }
    .trow-meta { white-space: normal; }
    .trow-date { min-width: 0; }
    .tgroup > summary { padding: 10px 14px; }
    .tgroup-none, .trow + .trow { border-top-color: var(--line); }

    /* Work clock: full-width action, tighter journal rows.
       The regular/overtime split is hidden on narrow screens - the day
       row keeps date, segment count and total; the split lives in the
       Excel export and on wider screens. */
    .clock { padding: 20px 14px 22px; }
    .clock-time { font-size: 2.1rem; }
    .clock-btn { width: 100%; min-width: 0; }
    .day > summary, .shift > summary { padding: 10px 14px; }
    .day-split { display: none; }
    .shift-form { padding: 2px 14px 14px; }
    .shift-note { flex: 1 1 100%; }
    .shift-actions .btn { flex: 1 1 auto; }

    /* Notes: one card per row, actions share the width; bigger colour dots to tap. */
    .notes-grid { gap: 10px; }
    .note-actions .btn { flex: 1 1 auto; }
    .swatches { gap: 14px; }
    .swatch-dot { width: 36px; height: 36px; flex-basis: 36px; }
    summary > .swatch-dot { width: 16px; height: 16px; flex-basis: 16px; }

    /* Dashboard stat cards: two per row, tighter. */
    .cards-4 { gap: 10px; }
    .stat-card { padding: 14px 10px; }
    .stat-num { font-size: 1.5rem; }

    .msg { padding: 10px 12px; }
    .msg-head { gap: 6px 10px; }
    .chip { padding: 3px 10px; }
}

@media (prefers-reduced-motion: reduce) {
    * { animation: none !important; transition: none !important; }
}
