/* ---- Self-hosted web fonts (no third-party requests; preloaded in App.razor) ----
   Archivo = latin variable subset (weights 100-900). Material Symbols = a subset of ONLY the icons
   the app uses (markup + CSS content:'…'); regenerate both via Google Fonts css2 when adding glyphs. */
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 100 900;
    font-stretch: 100%;
    font-display: swap;
    src: url('/fonts/archivo-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Material Symbols Outlined';
    font-style: normal;
    font-weight: 100 700;
    font-display: block;
    src: url('/fonts/material-symbols-subset.woff2') format('woff2');
}

html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    margin: 0;
    background-color: #fbfbfd;
}

.page{
    flex: 1;
}

/* Spinning icon for in-progress actions (e.g. the Export button while the workbook is built). */
@keyframes spin {
    to { transform: rotate(360deg); }
}

.material-symbols-outlined.spin {
    animation: spin 1s linear infinite;
}


h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ============================================================
   VibaCloud UI — custom styling (replaces Bootstrap).
   Targets the class names used across the app's pages so the
   markup doesn't need to change. Kept in this one file.
   ============================================================ */
:root {
    /* Brand azure, driving both the button fill and link text. Measured: #0076c9 is 4.74:1 against a
       white button label and 4.58:1 as link text on the #fbfbfd page, so it clears AA in both roles
       with little to spare. Lighten it and links go below AA first. */
    --vc-primary: #0076c9;
    --vc-primary-hover: #0063ab;
    --vc-danger: #dc2626;
    --vc-danger-hover: #b91c1c;
    --vc-text: #1f2933;
    /* Secondary/muted text. #6b7280 reads clearly on the near-white background (the old #b9b9b9 was too
       light and failed contrast); it matches the fallback the page LESS files already use. */
    --vc-muted: #6b7280;
    --vc-border: #aaa;
    --vc-subtle: #f9fafb;
    --vc-radius: 4px;
    /* Interactive controls (button, input, select, icon button) share one radius, border and elevation
       so they line up when they sit on the same row, e.g. the week picker between its two chevrons.
       Panels and alerts stay on --vc-radius: they are surfaces, not controls.
       --vc-control-lift is the SINGLE source for how far everything sits off the page: .btn derives
       its --vc-btn-lift from it, and the inputs use it directly. Change it here, not per component,
       or the row stops matching. */
    /* Full pill. Single-line controls are shorter than they are wide, so 999px resolves to a
       half-height cap; see the textarea rule below for the one case that can't take it. This also
       puts buttons and inputs in the same geometry as the status badges, which are already 999px. */
    --vc-control-radius: 999px;
    --vc-control-border: #ccc;
    --vc-control-lift: 2px;
    --vc-control-lip: #d3dce4;
    --vc-control-ambient: rgba(15, 23, 42, 0.13);
    /* One height for every control that sits in a filter/nav row: the Draft Timesheet week nav and
       the Billing / Invoices / Reports filter bars all read from this, so those rows can't drift out
       of step again. 44px is the WCAG 2.5.5 touch-target minimum; the bump below is for the mobile
       timesheet grid, where this is the most-tapped control on the page. */
    --vc-control-h: 44px;
}

@media (max-width: 1150px) {
    :root {
        --vc-control-h: 50px;
    }
}

body {
    color: var(--vc-text);
    line-height: 1.5;
}

.page main {
    padding: 1.5rem 2rem;
}

h1 {
    font-size: 1.6rem;
    font-weight: 600;
    margin: 0 0 1rem;
}

a {
    color: var(--vc-primary);
}

/* ---- Buttons ----
   "Pushable" buttons: each one sits on a solid lip of a darker shade of its own fill, and pressing
   it drops the face by exactly the lip height so the button lands flush on the surface. The lip and
   the ambient shadow are two layers of the SAME box-shadow, set per variant via --vc-btn-lip.

   Two things hold this together and will break it if changed independently: the translateY on
   :active must equal the lip offset (both --vc-btn-lift), or the button either floats or overshoots;
   and the press transition is short (0.06s) while the release is longer, which is what makes it feel
   sprung rather than sluggish.

   Vertical padding is deliberately unchanged: .btn is also the base for the small buttons inside the
   data grids, and the lip is drawn with box-shadow so it costs no layout height anywhere. */
.btn {
    --vc-btn-lift: var(--vc-control-lift);
    --vc-btn-lip: #c9d3db;
    --vc-btn-ambient: rgba(15, 23, 42, 0.16);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    font: inherit;
/*    font-weight: 600;*/
    line-height: 1.2;
    padding: 0.6rem 1.2rem;
    border: 1px solid transparent;
    border-radius: var(--vc-control-radius);
    cursor: pointer;
    text-decoration: none;
    box-shadow: 0 var(--vc-btn-lift) 0 var(--vc-btn-lip),
                0 calc(var(--vc-btn-lift) + 2px) 10px -4px var(--vc-btn-ambient);
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease,
                box-shadow 0.12s ease, transform 0.12s ease;
}

/* Hover lifts the face 1px and grows the lip by the same 1px, so the BOTTOM of the lip never moves:
   the button rises off a fixed ground line instead of the whole thing drifting upward. Movement is
   the main hover feedback here because the fills have no room to brighten (see .btn-primary). */
.btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 calc(var(--vc-btn-lift) + 1px) 0 var(--vc-btn-lip),
                0 calc(var(--vc-btn-lift) + 4px) 14px -4px var(--vc-btn-ambient);
}

/* The press: face drops onto the lip, lip collapses to nothing, ambient shadow tightens. Same ground
   line again, so rest → hover → press is one continuous travel. Faster than the release so it snaps
   back. Declared after :hover, and equal specificity, so pressing beats hovering. */
.btn:active {
    transform: translateY(var(--vc-btn-lift));
    box-shadow: 0 0 0 var(--vc-btn-lip), 0 1px 2px rgba(15, 23, 42, 0.2);
    transition-duration: 0.06s;
}

/* Pointer-only. A tap on mobile fires :active with no hover beforehand, and the drop reads as lag. */
@media (hover: none) {
    .btn { transition-duration: 0s; }
}

/* Respect a reduced-motion preference: keep the lip, drop the movement. */
@media (prefers-reduced-motion: reduce) {
    .btn, .btn:active { transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; }
    .btn:active { transform: none; }
}

.btn:focus-visible {
    outline: 2px solid var(--vc-primary);
    outline-offset: 2px;
}

/* Fills are flat, not gradients: the lip supplies the depth now, and a gradient on top of it reads
   as two competing light sources. --vc-primary is as bright as this azure goes with a white 16px/600
   label still clearing the 4.5:1 AA floor (4.74:1); #0088e0 is 3.75:1 and #00aeff 2.47:1.
   Each lip is a darker shade of its own fill, never a generic grey, or the button looks pasted on. */
.btn-primary {
    --vc-btn-lip: #00558f;
    --vc-btn-ambient: rgba(0, 85, 143, 0.34);
    background: var(--vc-primary);
    color: #fff;
}

/* Hover DARKENS. --vc-primary is already the brightest this azure goes at AA (4.74:1), so the usual
   brighten-on-hover would push the label under the floor: #0080d8 measures 4.13:1. */
.btn-primary:hover {
    background: #006cb8;
}

/* Red has no headroom to lighten (--vc-danger is itself only 4.8:1), so hover darkens instead. */
.btn-danger {
    --vc-btn-lip: #9b1c1c;
    --vc-btn-ambient: rgba(155, 28, 28, 0.32);
    background: var(--vc-danger);
    color: #fff;
}

.btn-danger:hover {
    background: #c81f1f;
}

/* The neutral button gets the same construction so the pair presses alike: white face, grey lip.
   Its border colour is its own rather than --vc-border (#aaa), which reads as a 2010s form control. */
.btn-outline-secondary {
    --vc-btn-lip: #d3dce4;
    --vc-btn-ambient: rgba(15, 23, 42, 0.13);
    background: #fff;
    color: var(--vc-text);
    border-color: #aaa;
}

.btn-outline-secondary:hover {
    background: #f3faff;
    border-color: #bfdcf0;
}

/* A button that reads as an inline text link (e.g. "Show all events"). */
.btn-link {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--vc-primary);
    text-decoration: underline;
    cursor: pointer;
}

.btn-link:hover {
    color: var(--vc-primary-hover);
}

/* ---- Cookie notice (bottom of page) ---- */
.cookie-banner {
    position: fixed;
    left: 1rem;
    right: 1rem;
    bottom: 1rem;
    z-index: 1100;
    display: flex;
    align-items: center;
    gap: 1rem;
    max-width: 64rem;
    margin: 0 auto;
    padding: 0.85rem 1.1rem;
    background: #fff;
    border: 1px solid var(--vc-border);
    border-radius: var(--vc-radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.15);
}

.cookie-banner[hidden] {
    display: none;
}

.cookie-banner-text {
    margin: 0;
    font-size: 0.9rem;
    color: var(--vc-text);
}

.cookie-banner-btn {
    flex: none;
    white-space: nowrap;
}

@media (max-width: 32rem) {
    .cookie-banner {
        flex-direction: column;
        align-items: stretch;
        text-align: center;
    }
}

/* ---- Tables ---- */
.table {
    width: 100%;
    border-collapse: collapse;
    margin: 1rem 0;
    font-size: 0.95rem;
}

.table thead th {
    text-align: left;
    font-weight: 600;
    color: var(--vc-muted);
    border-bottom: 2px solid var(--vc-border);
    padding: 0.6rem 0.75rem;
    white-space: nowrap;
}

.table tbody td {
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--vc-border);
}

.table tbody tr:hover {
    background: var(--vc-subtle);
}

.table.align-middle td,
.table.align-middle th {
    vertical-align: middle;
}

/* ---- Alerts ---- */
.alert {
    padding: 0.75rem 1rem;
    margin: 1rem 0;
    border: 1px solid transparent;
    border-radius: var(--vc-radius);
}

.alert-success {
    background: #ecfdf5;
    color: #065f46;
    border-color: #a7f3d0;
}

.alert-danger {
    background: #fef2f2;
    color: #991b1b;
    border-color: #fecaca;
}

.alert-warning {
    background: #fffbeb;
    color: #92400e;
    border-color: #fde68a;
}

.alert-info {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    background: #eff6ff;
    color: #1e40af;
    border-color: #bfdbfe;
}

.alert-info .material-symbols-outlined {
    flex: 0 0 auto;
    font-size: 1.25rem;
    line-height: 1.4;
}

.alert-link {
    font-weight: 600;
    color: inherit;
    text-decoration: underline;
}


/* ---- Badges ---- */
/* ---- Status badges ----
   Deliberately NOT built like the buttons. A badge is read, never clicked, so it stays flat, keeps
   the full 999px radius and never gets the lip: that difference is the signal that it isn't
   pressable. Giving "Approved" a pushable look would be a usability bug, not a style choice.

   What was actually wrong was the badges disagreeing with EACH OTHER. Two of them used a solid
   saturated fill with white text and the rest used a soft tint with dark text, so one status column
   showed two design languages, and the solid pair failed contrast badly at this 12px size
   (draft 2.28:1, submitted 2.77:1). Every variant is now one soft family: pale tint, deep text of
   the same hue, and a mid-tone hairline so the chip still has an edge on a white grid row.
   Variants live here, in site.less (approved / reopen) and invoices.less (sent / paid / void /
   overdue); all of them are measured against 4.5:1 at 12px. */
.badge {
    display: inline-block;
    padding: 0.4rem 0.65rem;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1;
    border: 1px solid transparent;
    border-radius: 999px;
    /* Neutral default, so a variant that forgets to set a colour is still readable rather than
       white-on-near-white. Previously this was #fff, which is why an unstyled badge vanished. */
    color: #44536b;
    background: #eef1f5;
    border-color: #d3dae4;
    box-sizing: border-box;
    text-align: center;
}

/* Neutral chip ("all day" on Import, "Reopened xN" on My Timesheets). */
.bg-secondary {
    background: #eef1f5;
    color: #44536b;
    border-color: #d3dae4;
}

.badge-draft {
    background: #eef1f5;
    color: #44536b;
    border-color: #d3dae4;
}

.badge-submitted {
    background: #e6f1fb;
    color: #185fa5;
    border-color: #c2ddf5;
}

/* ---- Form controls ---- */
/* Inputs sit on the same lip and ambient shadow as the neutral button, so a control row (the week
   picker between its two chevrons) sits on one plane. They do NOT get the press: the lip is a
   statement about elevation, and only .btn:active collapses it. An earlier version recessed the
   inputs instead, as the physical opposite of a raised button, but at this lift the inset was too
   faint to read as deliberate and just looked like a missing shadow.
   Padding is a touch tighter horizontally than a button: a text field doesn't need the shoulders. */
.form-control,
.form-select {
    box-shadow: 0 var(--vc-control-lift) 0 var(--vc-control-lip),
                0 calc(var(--vc-control-lift) + 2px) 10px -4px var(--vc-control-ambient);
}

/* The native arrow sits hard against the edge and reserves an amount of space we can't control, which
   on a pill reads as cramped: the round cap is already eating width the text can't use. So the native
   control is switched off and the chevron is drawn as an inline SVG background, which lets the right
   padding, the arrow's inset and the gap between text and arrow each be set deliberately.

   IMPORTANT: anything restyling a select must use background-color, NOT the background shorthand, or
   it wipes this arrow and leaves a select with no affordance at all (appearance:none has already
   removed the native one). See .form-select:disabled below and the auth screens in login.less. */
.form-select {
    font: inherit;
    /* Right padding clears the arrow zone; left is roomier than a rectangle needs, for the pill cap. */
    padding: 0.6rem 2rem 0.6rem 1rem;
    border: 1px solid var(--vc-control-border);
    border-radius: var(--vc-control-radius);
    background-color: #fff;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1.4 1.4 6 6l4.6-4.6' fill='none' stroke='%236b7280' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.85rem center;
    background-size: 11px 8px;
    color: var(--vc-text);
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

/* Firefox keeps a focus inner-outline on select; and on Windows the option list otherwise inherits
   the transparent-ish styling above, which renders unreadable in some themes. */
.form-select option {
    color: var(--vc-text);
    background-color: #fff;
}


/* background-COLOR, not the shorthand: the shorthand would drop the chevron and leave a disabled
   select looking like a plain text box. The arrow is dimmed to match the muted label instead. */
.form-select:disabled {
    background-color: var(--vc-subtle);
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1.4 1.4 6 6l4.6-4.6' fill='none' stroke='%23aab1bb' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    color: var(--vc-muted);
}

input[type="checkbox"] {
    width: 1.05rem;
    height: 1.05rem;
    accent-color: var(--vc-primary);
    cursor: pointer;
    vertical-align: middle;
}

.form-control {
    font: inherit;
    width: 100%;
    padding: 0.5rem 0.7rem;
    border: 1px solid var(--vc-control-border);
    border-radius: var(--vc-control-radius);
    background: #fff;
    color: var(--vc-text);
    box-sizing: border-box;
}

/* The one control the pill can't apply to. On a multi-line box 999px resolves to half the HEIGHT,
   which bows the left and right edges into arcs and eats the first and last lines of text. These
   keep a rounded rectangle, sized to read as the same family. Used by the reopen note, the reject
   comment and the invoice generator's address/payment fields. */
textarea.form-control {
    border-radius: 14px;
    padding: 0.6rem 0.85rem;
}

/* Number inputs: drop the native spin buttons. They reserve width INSIDE the content box, which on
   a narrow field (the weekly grid's day cells are 64px) clips the value: "14.25" measured
   scrollWidth 65 against clientWidth 62. They're also near-useless at our step sizes, since every
   number input in the app steps by 0.25 or less, so 14.25 would be 57 clicks. Typing is the only
   real input method here. */
.form-control[type="number"]::-webkit-outer-spin-button,
.form-control[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

.form-control[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

/* Focus keeps the control on its lip and adds the azure ring outside it, so the field doesn't drop
   to the page the moment you click into it. */
.form-control:focus,
.form-select:focus {
    outline: none;
    border-color: var(--vc-primary);
    box-shadow: 0 var(--vc-control-lift) 0 var(--vc-control-lip),
                0 0 0 3px rgba(0, 118, 201, 0.15);
}

/* Disabled controls sit flush, same as a disabled button: nothing raised, nothing to interact with. */
.form-control:disabled,
.form-select:disabled {
    box-shadow: none;
}

/* The native date/time picker button is near-black by default, which is the heaviest thing in the
   week nav. Mute it to sit with the chevrons, full strength on hover. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
    opacity: 0.5;
    cursor: pointer;
}

input[type="date"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:hover::-webkit-calendar-picker-indicator {
    opacity: 1;
}

.form-label {
    display: block;
    font-weight: 600;
    font-size: 0.9rem;
    margin-bottom: 0.3rem;
}

.form-field {
    margin-bottom: 1rem;
}

.form-hint {
    color: var(--vc-muted);
    font-size: 0.85rem;
    margin: 0.3rem 0 0;
}

.form-check {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.form-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.25rem;
}

/* ---- Modal ---- */
.modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 4rem 1rem;
    /* Scroll the backdrop when a card is taller than the viewport (e.g. on a phone) so its bottom — and
       any action buttons — stay reachable. align-items: flex-start keeps the top from being clipped. */
    overflow-y: auto;
    background: rgba(0, 0, 0, 0.45);
}

@media (max-width: 640px) {
    .modal-backdrop {
        padding: 1rem;
    }
}

.modal-card {
    width: 100%;
    max-width: 28rem;
    background: #fff;
    border-radius: var(--vc-radius);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
    overflow: hidden;
    padding: 30px;
}

.modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.85rem 1rem;
/*    border-bottom: 1px solid var(--vc-border);*/
}

.modal-title {
    margin: 0;
    font-size: 1.1rem;
    font-weight: 600;
}

.modal-close {
    display: inline-flex;
    padding: 0.15rem;
    border: none;
    border-radius: 6px;
    background: none;
    color: var(--vc-muted);
    cursor: pointer;
}

.modal-close:hover {
    background: var(--vc-subtle);
    color: var(--vc-text);
}

.modal-body {
    padding: 1rem;
}

/* ---- Page toolbar (title + action) ---- */
.page-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1rem;
    h1{
        span{
            font-weight: 200;
        }
    }
}

.toolbar-title {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}
    .toolbar-title h1 {
        margin: 0;
    }

.toolbar-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Contextual link from an app page to its Help Centre guide (GuideLink.razor); sits in the
   page toolbar opposite the title. */
.guide-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.85rem;
    color: var(--vc-muted);
    text-decoration: none;
    white-space: nowrap;
}

    .guide-link:hover {
        color: var(--vc-text);
        /* text-decoration: underline; */
    }

    .guide-link .material-symbols-outlined {
        font-size: 1.1rem;
    }

/* On narrow screens stack the title above the actions, and let the buttons
   wrap and stretch full-width so they don't crowd the heading. */
@media (max-width: 930px) {

    .page main {
        padding: 1.5rem 1rem;
    }

    .page-toolbar {
        flex-direction: column;
        align-items: center;
        gap: 0;
    }

    .toolbar-title {
        margin-bottom: 20px;
        flex-direction: column;
    }

    .toolbar-actions {
        flex-wrap: wrap;
    }

        .toolbar-actions > .btn {
            flex: 1 1 auto;
            justify-content: center;
        }
}

/* The print document is built into the page but only revealed by the @media print rules below. */
.print-only {
    display: none;
}

.week-nav {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.week-nav .week-picker {
    width: auto;
}

.week-nav .week-range {
    margin-left: 0.5rem;
    color: var(--vc-muted);
    font-weight: 600;
}

/* Submitted/Approved pill on the draft grid: pushed to the right edge of the nav row so it sits
   directly above the grid, where the locked state is actually looked for. */
.week-nav .week-status {
    margin-left: auto;
}

/* A bare icon control. Deliberately flat, no lip: it's a small in-row affordance, and giving it the
   full pushable treatment would put more visual weight on it than the real buttons beside it. It
   still tracks the shared control radius and border so it doesn't read as a leftover. */
.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.4rem;
    border: 1px solid var(--vc-control-border);
    border-radius: var(--vc-control-radius);
    background: #fff;
    color: var(--vc-text);
    cursor: pointer;
}

.icon-btn:hover:not(:disabled) {
    background: var(--vc-subtle);
}

.icon-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ---- Material Symbols icons ----
   Self-sufficient: these base properties (font-family, ligature, layout) used to come from Google's
   stylesheet, which we no longer load — the glyph is rendered from the ligature text (e.g. "add"), so
   font-feature-settings:'liga' and white-space:nowrap are required for it to resolve correctly. */
.material-symbols-outlined {
    font-family: 'Material Symbols Outlined';
    font-weight: normal;
    font-style: normal;
    font-size: 1.25rem;
    line-height: 1;
    vertical-align: middle;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    -webkit-font-feature-settings: 'liga';
    font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
    /* default optical settings */
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}

/* ---- Utility classes used in markup ---- */
/* Visually hidden but available to screen readers (e.g. data tables behind SVG charts). */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.d-flex { display: flex; }
.d-inline-block { display: inline-block; }
.justify-content-between { justify-content: space-between; }
.align-items-center { align-items: center; }
.gap-2 { gap: 0.5rem; }
.mb-3 { margin-bottom: 1rem; }
.ms-1 { margin-left: 0.25rem; }
.me-1 { margin-right: 0.25rem; }
.me-2 { margin-right: 0.5rem; }
.rounded-circle { border-radius: 50%; }

/* Stacked org/project pickers inside a grid cell. */
.dg-picker {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    width: 100%;
}

.dg-picker-row {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.dg-picker-row .form-select {
    flex: 1;
    min-width: 0;
}




#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }


/* ---- Print / Save-as-PDF (View Timesheet) ---- */
@media print {
    /* A4 portrait — the report is sized to fit the page width with no horizontal scrolling. */
    @page {
        size: A4 portrait;
        margin: 14mm;
    }

    /* Hide all app chrome and interactive UI: nav/header, footer, error bar, on-screen view & buttons. */
    header,
    footer,
    #blazor-error-ui,
    .modal-backdrop,
    .screen-only {
        display: none !important;
    }

    /* Reset page wrappers so the print document starts at the top with no stray margins. */
    body,
    .page,
    main {
        margin: 0 !important;
        padding: 0 !important;
        background: #fff !important;
        color: #000 !important;
    }

    /* Reveal the print-only document. */
    .print-only {
        display: block !important;
        color: #000;
    }

    .print-document {
        font-size: 10pt;
        line-height: 1.4;
    }

    /* ---- Title ---- */
    .print-header {
        margin: 0 0 1rem;
        padding-bottom: 0.4rem;
        border-bottom: 2px solid #000;
    }

    .print-title {
        margin: 0;
        font-size: 16pt;
    }

    /* ---- Document metadata: two columns above the grid. ---- */
    .print-meta {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0.2rem 2rem;
        margin: 0 0 1rem;
    }

    .print-meta .meta-item {
        display: flex;
        gap: 0.5rem;
    }

    .print-meta .meta-label {
        font-weight: bold;
        min-width: 9rem;
    }

    .print-meta .meta-label::after {
        content: ":";
    }

    /* ---- Totals summary: borderless, right-aligned below the grid (invoice-style). ---- */
    .print-figures {
        width: max-content;
        min-width: 16rem;
        margin: 1rem 0 0 auto; /* whitespace above + push to the right edge */
    }

    .print-figures .fig {
        display: flex;
        justify-content: space-between;
        gap: 2rem;
        padding: 0.1rem 0;
    }

    .print-figures .fig-label::after {
        content: ":";
    }

    .print-figures .fig-value {
        text-align: right;
        font-variant-numeric: tabular-nums;
    }

    /* Subtle separator above the totals; Total Hours + Total Value shown in bold. */
    .print-figures .fig-totals {
        margin-top: 0.25rem;
        padding-top: 0.3rem;
        border-top: 1px solid #000;
    }

    .print-figures .fig-total {
        font-weight: bold;
    }

    /* ---- Detail table: full visible borders, repeats its header per page, avoids splitting rows. ---- */
    .print-table {
        width: 100%;
        border-collapse: collapse;
        font-size: 9pt;
    }

    .print-table th,
    .print-table td {
        border: 1px solid #000;
        padding: 4px 6px;
        text-align: left;
        vertical-align: top;
    }

    .print-table thead th {
        background: #eee !important;
        font-weight: bold;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    .print-table thead {
        display: table-header-group; /* repeat header on every printed page */
    }

    .print-table tr {
        page-break-inside: avoid;
        break-inside: avoid;
    }

    /* Numeric columns (Rate, daily hours, Total, Value) right-aligned; labels stay left-aligned. */
    .print-table .num {
        text-align: right;
        white-space: nowrap;
    }

    /* Weekly grid: many narrow day columns, so shrink the type and tighten cell padding to fit portrait. */
    .print-week {
        font-size: 8.5pt;
    }

    .print-week th,
    .print-week td {
        padding: 3px 5px;
    }

    .print-week thead th.num {
        text-align: center;
    }

    /* Non-billable lines: no Bill column on the report, so dim the row instead. */
    .print-week tbody tr.is-nonbillable td {
        color: #777;
    }

    /* Daily Total row: clearly set apart — bold, thicker top rule, light grey band. */
    .print-table tfoot .print-totals td {
        font-weight: bold;
        border-top: 2px solid #000;
        background: #f2f2f2 !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
}


/* ---- Settings dashboard cards ---- */
.settings-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 1rem;
    margin: 1rem 0 2rem;
}

.settings-card {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 1.1rem 1.2rem;
    border: 1px solid var(--vc-border);
    border-radius: var(--vc-radius);
    background: #fff;
    color: var(--vc-text);
    text-decoration: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

a.settings-card:hover {
    border-color: var(--vc-primary);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
}

.settings-card-icon {
    font-size: 1.9rem;
    color: var(--vc-primary);
}

.settings-card-title {
    font-weight: 600;
    font-size: 1.05rem;
}

.settings-card-desc {
    color: var(--vc-muted);
    font-size: 0.9rem;
}

.settings-card.is-disabled {
    opacity: 0.7;
    background: var(--vc-subtle);
    cursor: default;
}

.settings-card-soon {
    align-self: flex-start;
    margin-top: 0.2rem;
    padding: 0.1rem 0.5rem;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--vc-muted);
    border: 1px solid var(--vc-border);
    border-radius: 999px;
}

/* Settings → Danger Zone: deliberately subdued (a soft warning tint, not an aggressive red block). */
.danger-zone {
    margin-top: 2.5rem;
    padding: 1.25rem 1.5rem;
    border: 1px solid #fecaca;
    border-radius: var(--vc-radius);
    background: #fef9f9;
}

.danger-zone-title {
    margin: 0 0 0.75rem;
    font-size: 1.05rem;
    color: var(--vc-danger);
}

.danger-zone-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.danger-zone-subtitle {
    margin: 0 0 0.25rem;
    font-size: 1rem;
}

.danger-zone-desc {
    margin: 0;
    max-width: 38rem;
    color: var(--vc-muted);
    font-size: 0.9rem;
}

/* CSS-only modal: a hidden checkbox toggles the overlay (label-for), so the Danger Zone delete flow
   works without the Blazor circuit. The card sits above a full-bleed dismiss label (click-outside close). */
.vc-modal-toggle {
    position: absolute;
    width: 0;
    height: 0;
    opacity: 0;
    pointer-events: none;
}

.vc-modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1000;
    align-items: flex-start;
    justify-content: center;
    padding: 4rem 1rem;
    /* Scroll the overlay itself when the card is taller than the viewport (e.g. this modal on a phone),
       so the bottom of the card — and the Delete button — stays reachable. */
    overflow-y: auto;
    background: rgba(0, 0, 0, 0.45);
}

.vc-modal-toggle:checked ~ .vc-modal-overlay {
    display: flex;
}

/* Fixed (not absolute) so the click-outside-to-close backdrop covers the whole viewport at any scroll
   position, behind the card. */
.vc-modal-dismiss {
    position: fixed;
    inset: 0;
    cursor: default;
}

.vc-modal-card {
    position: relative;
    z-index: 1;
}

@media (max-width: 640px) {
    .vc-modal-overlay {
        padding: 1rem;
    }
}

/* Delete-account submit button: swap the label for a spinner while the (full-page) POST is in flight. */
#vc-delete-submit .btn-spinner {
    display: none;
}

#vc-delete-submit.is-deleting .btn-label {
    display: none;
}

#vc-delete-submit.is-deleting .btn-spinner {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

/* Stay danger-red (not greyed) while deleting, even though the button is disabled to block double-submit. */
#vc-delete-submit.is-deleting {
    background: var(--vc-danger);
    color: #fff;
    opacity: 0.85;
    cursor: progress;
}

/* Delete-account modal: the list of what gets removed. */
.delete-account-list {
    margin: 0.5rem 0 1rem;
    padding-left: 1.25rem;
}

.delete-account-list li {
    margin: 0.2rem 0;
}

/* Post-deletion confirmation banner on the home page. */
.home-deleted-notice {
    max-width: 40rem;
    margin: 1rem auto;
}

/* Connected Calendars page: one row per provider with its connection state and action. */
.calendar-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-width: 32rem;
    margin-top: 1rem;
}

.calendar-row {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 0.9rem 1rem;
    border: 1px solid var(--vc-border);
    border-radius: 10px;
    background: var(--vc-card, #fff);
}

.calendar-badge {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border-radius: 8px;
    background-color: #fff;
    background-position: center;
    background-repeat: no-repeat;
    background-size: 22px;
    border: 1px solid var(--vc-border);
}

.calendar-badge.google {
    background-image: url(/images/icon_google.png);
}

.calendar-badge.microsoft {
    background-image: url(/images/icon_microsoft.png);
}

.calendar-row-text {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
    margin-right: auto;
}

.calendar-row-title {
    font-weight: 600;
}

.calendar-row-status {
    font-size: 0.85rem;
    color: var(--vc-muted);
}

.calendar-tag {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    border: 1px solid var(--vc-border);
    border-radius: 999px;
    color: var(--vc-muted);
}

.calendar-tag.is-connected {
    color: #fff;
    background: var(--vc-success, #1f9d55);
    border-color: transparent;
}

.calendar-row-action {
    flex: 0 0 auto;
}

.calendar-row-action form {
    margin: 0;
}




.btn-primary:disabled {
    background: var(--vc-muted);
    cursor: not-allowed;
}

/* Any disabled button (e.g. the Delete-account confirm button before DELETE is typed) reads as
   inactive: flat grey, sitting flush with no lip, so there is visibly nothing to press. */
.btn:disabled {
    background: var(--vc-muted);
    border-color: transparent;
    color: #fff;
    opacity: 0.65;
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

/* Import screen styles live in wwwroot/css/import.less (linked from Import.razor). */

@media (max-width: 640px) {
    .guest-banner {
        flex-direction: column;
        align-items: flex-start;
    }
}

/* ---- Guest mode: standing "save your work" banner ---- */
.guest-banner {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.85rem 1rem;
    margin-bottom: 1.25rem;
    background: var(--vc-subtle);
    border: 1px solid var(--vc-primary);
    border-radius: var(--vc-radius);
}

.guest-banner-icon {
    flex: 0 0 auto;
    color: var(--vc-primary);
    font-size: 1.5rem;
}

.guest-banner-text {
    flex: 1;
    font-size: 0.9rem;
    line-height: 1.4;
}

.account-guest-cta {
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    text-decoration: none;
}

/* ---- Login / Join split-panel styling lives in css/login.less ---- */

/* ---- Create-account modal ---- */
.account-modal-intro {
    margin: 0 0 1rem;
    color: #555;
}

.account-modal-providers {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.account-modal-providers .btn {
    border: solid 1px #777;
    color: #555;
    padding: 12px 12px 12px 56px;
    background-position: 14px center;
    background-repeat: no-repeat;
    background-size: 28px;
    text-decoration: none;
}

.account-modal-providers .btn:hover {
    border-color: var(--vc-primary);
    background-color: var(--vc-subtle);
}

.account-modal-providers .microsoft {
    background-image: url(/images/icon_microsoft.png);
}

.account-modal-providers .google {
    background-image: url(/images/icon_google.png);
}

.account-modal-divider {
    display: flex;
    align-items: center;
    text-align: center;
    color: var(--vc-muted);
    font-size: 0.8rem;
    margin: 1rem 0;
}

.account-modal-divider::before,
.account-modal-divider::after {
    content: "";
    flex: 1;
    border-bottom: 1px solid var(--vc-border);
}

.account-modal-divider span {
    padding: 0 0.75rem;
}

.account-modal-form {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.account-modal-submit {
    margin-top: 0.75rem;
}

.account-modal-switch {
    margin: 0.85rem 0 0;
    font-size: 0.85rem;
    color: #555;
}

/* "Remember me" + "Forgot your password?" share a row under the password field. */
.account-modal-formrow {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin: 0.35rem 0 0;
    font-size: 0.85rem;
}

.account-modal-remember {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
    user-select: none;
}

.account-modal-remember input {
    width: 1rem;
    height: 1rem;
    margin: 0;
    accent-color: var(--vc-primary);
    cursor: pointer;
}


#time-zone{
  max-width: 100%;
}




/* Quiet related-guide links at the foot of the page — one muted line, dot-separated. */
.dt-guides {
    margin-top: 2.5rem;
    padding-top: 1rem;
/*    border-top: 1px solid #e3e7ee;*/
    font-size: 0.85rem;
    color: #6b7280;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;

    h2{
        margin: 10px 0;
    }

    .dt-guides-heading {
        font-weight: 600;
        margin-right: 0.5rem;
    }

    ul {
        display: inline;
        list-style: none;
        margin: 0;
        padding: 0;
    }

    li {
        display: inline;
        white-space: nowrap;
    }

        li + li::before {
            content: "\00b7";
            margin: 0 0.5rem;
            white-space: normal;
        }

    a {
        color: inherit;
        text-decoration: none;
        display: flex;
        align-items: center;
        justify-content: center;
        min-height: 30px;

        &:hover {
            color: #15171c;
        }
    }
}



@media (max-width: 720px) {

    body {
        font-size: 20px;
    }

    .week-nav {
        justify-content: center;
    }

        .week-nav + p {
            text-align: center;
        }
}
