/* Grafters minimal CSS — most styling now comes from MudBlazor's theme
   system (configured in App.razor). What stays here:
   - HTML/body baseline so the page is dark BEFORE Blazor mounts.
   - Centered branded splash while WASM downloads + initialises.
   - Blazor runtime error banner styling.
   - Brand mark pulse animation (signature motion on page load).
   - <pre> styling for free-text Notes / Descriptions on detail pages. */

/* ---------------------------------------------------------------- */
/* Baseline reset only. Do NOT hardcode a background/colour here — that
   bleeds through behind MudBlazor content in light mode (the page went
   black). MudThemeProvider owns the themed background; the FOUC script in
   index.html paints documentElement for the brief pre-mount window. */
html, body {
    margin: 0;
    padding: 0;
    /* Theme-aware so the whole viewport (including any area MudBlazor's layout
       doesn't paint) follows the active palette. var() is undefined pre-mount,
       so the index.html FOUC script's inline colour covers the load window. */
    background-color: var(--mud-palette-background);
}

/* FocusOnNavigate (App.razor) moves focus to each page's h1 on navigation so
   screen readers announce the new page. The heading is not an interactive
   control the user tabs to, so suppress the focus ring the browser would
   otherwise draw as a box around the title on every load. */
h1:focus,
h1:focus-visible {
    outline: none;
}

/* ---------------------------------------------------------------- */
/* Splash — shown while WASM downloads. The default Blazor template puts
   an SVG with two circles + a sibling div with the loading percentage
   inside #app. After Blazor mounts it replaces #app entirely, so these
   selectors only fire pre-mount. */

.loading-progress {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 96px;
    height: 96px;
    transform: translate(-50%, -50%);
}

.loading-progress circle {
    fill: none;
    stroke: #2c2f35;
    stroke-width: 6;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
}

.loading-progress circle:last-child {
    stroke: #bba96c;
    stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 25%) * 0.8), 500%;
    transition: stroke-dasharray 0.05s ease-in-out;
    animation: grafters-spin 1.4s linear infinite;
}

@keyframes grafters-spin {
    from { transform: rotate(-90deg); }
    to   { transform: rotate(270deg); }
}

.loading-progress-text {
    position: fixed;
    top: calc(50% + 64px);
    left: 50%;
    transform: translateX(-50%);
    color: #bba96c;
    font-weight: 700;
    letter-spacing: 0.06em;
    font-size: 1.1rem;
}

.loading-progress-text:after {
    content: 'Grafters';
}

/* ---------------------------------------------------------------- */
/* Runtime error banner (only visible if Blazor throws on the WASM side). */
#blazor-error-ui {
    background: #DF6F42;
    color: #ffffff;
    padding: 0.7rem 1.2rem;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1100;
    display: none;
    box-shadow: 0 -2px 8px rgba(0,0,0,0.4);
}
#blazor-error-ui .reload {
    color: #ffffff;
    margin-left: 0.6rem;
    text-decoration: underline;
}
#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 1rem;
    top: 0.7rem;
    font-size: 1.2rem;
}

/* ---------------------------------------------------------------- */
/* Brand mark pulse animation. Triggered on each page navigation by the
   .grafters-icon class on a <MudIcon>. */
@keyframes grafters-blink {
    0%, 100% { transform: rotate(0deg); }
    20%      { transform: rotate(-8deg); }
    40%      { transform: rotate(0deg); }
}

.grafters-icon {
    animation: grafters-blink 2.6s ease-in-out;
}

/* ---------------------------------------------------------------- */
/* Shared <pre> formatting for free-text Notes / Descriptions. */
.grafters-notes {
    background: var(--mud-palette-background-gray);
    color: var(--mud-palette-text-primary);
    padding: 0.6rem 0.8rem;
    border-radius: 6px;
    white-space: pre-wrap;
    font-family: inherit;
    font-size: 0.92rem;
    margin: 0;
}

/* ---------------------------------------------------------------- */
/* Job photo gallery + signature pad (Van / field). */
.grafters-photo-tile {
    position: relative;
    width: 120px;
    height: 120px;
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-background-gray);
}

.grafters-photo-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.grafters-photo-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding: 2px;
    background: linear-gradient(to bottom, rgba(0,0,0,0.45), transparent);
}

.grafters-sig-canvas {
    width: 100%;
    max-width: 600px;
    height: 220px;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 6px;
    background: #ffffff;
    touch-action: none;       /* let the pad capture touch strokes */
    cursor: crosshair;
}

/* Below md, the signature/photo dialogs fill the screen. Done in CSS rather
   than DialogOptions.FullScreen because picking options in C# needed
   IBrowserViewportService.GetCurrentBreakpointAsync, which hangs inside the
   Android BlazorWebView and stopped the dialogs opening at all. */
@media (max-width: 959.98px) {
    .mud-dialog.grafters-dialog-fill {
        width: 100vw;
        max-width: 100vw;
        height: 100%;
        max-height: 100%;
        margin: 0;
        border-radius: 0;
    }

    .grafters-dialog-fill .grafters-sig-canvas {
        max-width: none;
        height: min(55vh, 480px);
    }

    .grafters-dialog-fill .grafters-photo-center {
        min-height: 70vh;
    }
}

/* Full-size photo viewer: zoomable image wrapper (graftersImageZoom).
   touch-action:none hands pinch/pan to our handlers; overflow clips the
   scaled image to the dialog. */
.grafters-zoom-wrap {
    touch-action: none;
    overflow: hidden;
    max-width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 6px;
}

.grafters-zoom-wrap img {
    user-select: none;
    -webkit-user-drag: none;
    will-change: transform;
}

/* ---------------------------------------------------------------- */
/* v2 declarative form grids (IET schedules): grouped/rotated headers, */
/* units sub-row, sticky identity column.                            */
.grafters-grid {
    border-collapse: collapse;
    width: 100%;
    font-size: 0.8rem;
}

.grafters-grid th,
.grafters-grid td {
    border: 1px solid var(--mud-palette-lines-default);
    padding: 2px 6px;
    vertical-align: top;
}

.grafters-grid thead th {
    background: var(--mud-palette-background-gray);
    text-align: center;
    font-weight: 600;
    white-space: nowrap;
    vertical-align: middle;
}

.grafters-grid .grf-vhead {
    height: 96px;
    vertical-align: bottom;
}

.grafters-grid .grf-vhead > span {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    white-space: nowrap;
    display: inline-block;
    font-weight: 600;
}

.grafters-grid .grf-units td {
    font-size: 0.7rem;
    color: var(--mud-palette-text-secondary);
    text-align: center;
    font-style: italic;
    padding: 1px 6px;
}

.grafters-grid td.grf-right { text-align: right; }
.grafters-grid td.grf-center { text-align: center; }

.grafters-grid .grf-actions-col { width: 44px; text-align: center; }

.grafters-grid .grf-empty {
    color: var(--mud-palette-text-secondary);
    text-align: center;
    font-style: italic;
}

/* Pin the first identity column while the test-result columns scroll. */
.grafters-grid-wrap.grf-sticky .grafters-grid th:first-child,
.grafters-grid-wrap.grf-sticky .grafters-grid td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--mud-palette-surface);
}

.grafters-grid-wrap.grf-sticky .grafters-grid thead th:first-child {
    z-index: 2;
    background: var(--mud-palette-background-gray);
}

/* Schedule grids render both a scrollable table (desktop/print) and a stacked
   per-row card view (phones). Toggle by viewport so a 31-column IET schedule is
   usable on a phone; `.grf-stacked` forces the card view at any width. */
.grafters-grid-wrap .grf-cards-view { display: none; }
.grafters-grid-wrap .grf-table-view { display: block; }
.grafters-grid-wrap.grf-stacked .grf-cards-view { display: block; }
.grafters-grid-wrap.grf-stacked .grf-table-view { display: none; }

@media (max-width: 600px) {
    .grafters-grid-wrap .grf-cards-view { display: block; }
    .grafters-grid-wrap .grf-table-view { display: none; }
}

/* Skip-to-content link (WCAG 2.4.1): visually hidden until keyboard focus,
   then surfaces above the AppBar so keyboard users can jump past the chrome. */
.grafters-skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 2000;
    padding: 8px 16px;
    background: var(--mud-palette-primary);
    color: #fff;
    border-radius: 0 0 6px 0;
    text-decoration: none;
}

.grafters-skip-link:focus {
    left: 0;
}
