/* Page styles. Global (not component-scoped) so every stylesheet is a wwwroot file. */

/* Loaders (Components/Shared/LoadingRegion.razor, ChartRegion.razor, BusyButton.razor; rule in
   docs/agents/devexpress-blazor.md "Loaders").
   A region with nothing to show yet reserves the page area under the title, so the loaded page fills the same space. */
.loading-placeholder { min-height: calc(100vh - 14rem); }
/* A region inside a full-height flex page (Perubahan, Log, Progres, Laporan) passes the column and the page's gap on, so
   the grid keeps taking the height left. */
.loading-column { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; gap: inherit; }
/* A chart region keeps the chart's height (the page's min-height class) and shows its wait indicator while DevExpress
   marks the chart as not yet drawn. */
.chart-region { position: relative; }
.chart-region-wait { display: none; }
.chart-region:has(.dxbl-chart-first-loading) > .chart-region-wait {
    display: flex; position: absolute; inset: 0; align-items: center; justify-content: center; gap: 0.5rem;
    color: var(--dxds-color-content-neutral-subdued-rest);
}
/* Until the circuit has started the page cannot react; the top bar says so next to the project picker (MainLayout,
   prerendered HTML only). The anchor takes no width and the text sits out of the flow, so nothing moves when it goes.
   Phones have no room for it in the top bar. */
.prerender-wait-anchor { position: relative; width: 0; align-self: stretch; }
.prerender-wait {
    position: absolute; inset-inline-start: 0; top: 50%; transform: translateY(-50%); display: flex; align-items: center; gap: 0.5rem;
    white-space: nowrap; color: var(--dxds-color-content-neutral-subdued-rest); font-size: var(--dxds-font-size-base-sm); pointer-events: none;
}
@media (max-width: 767px) { .prerender-wait-anchor { display: none; } }
/* The wait indicator takes the place of the button text, which keeps its width (hidden, not removed). */
.busy-button-content { display: inline-grid; place-items: center; }
.busy-button-content > * { grid-area: 1 / 1; }
.busy-button-waiting .busy-button-text { visibility: hidden; }
/* DevExpress hides some components until its script has laid them out: the form layout (.dxbl-fl-loading, opacity 0),
   the drawer menu and an adaptive toolbar's items. Their prerendered HTML is final here, so the hiding only blanked
   the first page until the scripts loaded and blinked these parts once more when the circuit re-created them.
   Verified on DevExpress 26.1.5 (docs/agents/devexpress-blazor.md "Prerendering"); recheck after an upgrade. */
.dxbl-fl.dxbl-fl-loading { opacity: 1; }
/* ...except the body of a collapsed group, which only the script folds away. */
.dxbl-fl.dxbl-fl-loading dxbl-expandable-container[expanded-state="False"] { display: none; }
.navigation-drawer .dxbl-menu:not([data-dx-menu-loaded]) > * { opacity: 1; }
.dxbl-toolbar.dxbl-toolbar-adaptive.dxbl-loading > .dxbl-btn-toolbar > .dxbl-btn-group:not(.dxbl-toolbar-btn-ellipsis) { visibility: visible; width: auto; }

/* Surfaces (every page). The page area is the subdued neutral ground (layout.css); cards (DxFormLayoutGroup
   Decoration="Card", .dxbl-fl-gd) and the grids that stand on the page are raised white surfaces: one soft shadow, no
   border, a 12px radius, so elevation is declared once. A grid or tree list inside a card drops its own frame: the card
   is the frame. */
.page-content-container .dxbl-fl {
    --dxbl-fl-group-border-width: 0;
    --dxbl-fl-group-border-radius: var(--dxds-border-radius-120);
}
.page-content-container .dxbl-fl-gd > .dxbl-group { box-shadow: var(--dxds-box-shadow-xs); }
/* Only the root's outer frame goes: --dxbl-grid-border-width also draws the row and cell lines. */
.page-content-container .dxbl-fl .dxbl-grid { border-width: 0; }
.page-content-container .dxbl-grid:not(.dxbl-fl .dxbl-grid),
.page-content-container .dxbl-scheduler {
    border-color: transparent;
    border-radius: var(--dxds-border-radius-120);
    box-shadow: var(--dxds-box-shadow-xs);
}
/* Type inside cards: the caption is a title one step above the body (16px over 14px), the body reads at the base size
   (Small size mode would make it 12px); grids keep their own denser size. */
.page-content-container .dxbl-fl {
    --dxbl-fl-font-size: var(--dxds-font-size-base-md);
    --dxbl-fl-line-height: var(--dxds-line-height-base-md);
}
.page-content-container .dxbl-fl-gd > .dxbl-group {
    --dxbl-group-body-font-size: var(--dxds-font-size-base-md);
    --dxbl-group-body-line-height: var(--dxds-line-height-base-md);
    --dxbl-group-header-font-size: var(--dxds-font-size-title-sm);
    --dxbl-group-header-font-weight: var(--dxds-font-weight-title-default);
    --dxbl-group-header-line-height: var(--dxds-line-height-title-sm);
}

/* Hero card (Dasbor "Progres keseluruhan", Beranda project cards: CssClass="hero-card"): the project's one number on the
   drawer's brand gradient, the only blue surface of the page area. Text derives from the white foreground; secondary
   lines at 0.9 keep 4.5:1 on the light end of the gradient. */
.page-content-container .hero-card {
    --hero-ink: var(--dxds-color-content-neutral-default-static-dark-rest);
    --hero-ink-subdued: rgb(from var(--hero-ink) r g b / 0.9);
}
.page-content-container .hero-card > .dxbl-group {
    --dxbl-group-body-color: var(--hero-ink);
    --dxbl-group-header-bg: transparent;
    --dxbl-group-header-color: var(--hero-ink);
    background-color: var(--dxds-color-surface-primary-default-rest);
    background-image: linear-gradient(160deg, var(--dxds-color-surface-primary-default-rest) 0%, var(--dxds-primary-110) 100%);
    box-shadow: var(--dxds-box-shadow-sm);
    color: var(--hero-ink);
}
.page-content-container .hero-card .text-subdued { color: var(--hero-ink-subdued); }
.page-content-container .hero-card .dxbl-progress-bar {
    --dxbl-progress-bar-indicator-color: var(--hero-ink);
    --dxbl-progress-bar-track-color: rgb(from var(--hero-ink) r g b / 0.3);
}
.page-content-container .hero-card .dxbl-btn {
    --dxbl-btn-active-bg: rgb(from var(--hero-ink) r g b / 0.25);
    --dxbl-btn-active-color: var(--hero-ink);
    --dxbl-btn-color: var(--hero-ink);
    --dxbl-btn-hover-bg: rgb(from var(--hero-ink) r g b / 0.15);
    --dxbl-btn-hover-color: var(--hero-ink);
}
.page-content-container .hero-card :focus-visible { outline-color: var(--hero-ink); }
/* The page's one motion: the hero bar fills when DevExpress draws its value (first load, project switch). */
@media (prefers-reduced-motion: no-preference) {
    .page-content-container .hero-card .dxbl-progress-bar-indicator { transition: width 900ms cubic-bezier(0.16, 1, 0.3, 1); }
}

/* Move between two day-closes (Shared/MoveText.razor): drawn arrow plus text; colour repeats the direction on white
   cards, the hero card keeps its white ink (the arrow's shape still tells). */
.move { display: inline-flex; align-items: center; gap: 0.25rem; }
.move > .icon { flex: none; width: 1.125em; height: 1.125em; }
.move-up { color: var(--dxds-color-content-success-default-rest); }
.move-down { color: var(--dxds-color-content-danger-default-rest); }
.move-flat { color: var(--dxds-color-content-neutral-subdued-rest); }
.page-content-container .hero-card .move { color: var(--hero-ink); }
/* Dasbor Perubahan card: the move is the card's answer, one step above its lines. */
.period-move {
    font-size: var(--dxds-font-size-title-sm);
    font-weight: var(--dxds-font-weight-title-default);
    line-height: var(--dxds-line-height-title-sm);
}

/* Index */
/* Loader placeholder of the project cards (LoadingRegion): one row of cards (240px at 1440px). */
.loading-placeholder.index-projects-placeholder { min-height: 15rem; }
/* Trend line of a project card (ChartRegion): the chart's Height while it waits to draw. */
.index-trend { min-height: 2.5rem; }
/* Page menu card: the icon beside the page name and its one-line meaning; the whole row is the link. Its padding is
   the hover area, pulled out by the same amount so the icons line up with the card caption. */
.index-page-link {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    margin-inline: -0.5rem;
    padding: 0.5rem;
    border-radius: var(--dxds-border-radius-40);
    color: inherit;
    text-decoration: none;
}
/* A caption-less form layout item gets margin-top: auto (core.min.css, `.dxbl-fl .dxbl-fl-item .dxbl-fl-ctrl-nc`:
   bottom-aligned with captioned items of its row): beside a two-line description the one-line pages sat lower. */
.index-pages.dxbl-fl .dxbl-fl-item .dxbl-fl-ctrl-nc { margin-top: 0; }
.index-page-link:hover { background-color: var(--dxds-color-surface-neutral-default-hovered); }
.index-page-link:focus-visible { outline: 2px solid var(--dxds-color-border-focus-default); outline-offset: -2px; }
.index-page-link > .icon { flex: none; margin-top: 0.125rem; color: var(--dxds-color-content-primary-default-rest); }
.index-page-text { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }

/* Dashboard: everything else comes from DevExpress component parameters. */
/* A templated chart tooltip has no inner padding of its own. */
.chart-tooltip { padding: 0.25rem 0.5rem; }
/* DxFormLayoutGroup has no height parameter: CssClass lands on the stretched column, the card is its child (Dasbor,
   Beranda: the cards of one row are equally tall). */
.kpi-card > .dxbl-group { height: 100%; }
/* The aspect chart region keeps the chart's Height while it waits to draw (ChartRegion). */
.dashboard-aspect-chart { min-height: 40rem; }
/* The code chart region (Pekerjaan kode) keeps the chart's Height while it waits to draw: 18rem on a phone. */
.dashboard-code-chart { min-height: 16rem; }
@media (max-width: 767px) { .dashboard-code-chart { min-height: 18rem; } }

/* Period picker (Dasbor, Perubahan): presets, range and the history note on one row that wraps on a narrow page. The
   adaptive toolbar is flex: 1 1 auto by default (it shrank to 0px height in a column); here it takes its own width. */
.period-picker { display: flex; flex: none; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.75rem; }
.period-picker > .dxbl-toolbar { flex: none; }
.period-picker-note { color: var(--dxds-color-content-neutral-subdued-rest); font-size: var(--dxds-font-size-base-sm); }
/* Toolbar editors: the item takes its content's width, so the editor brings its own (range picker, grid search). */
.period-picker-range { width: 13rem; }
.toolbar-search { width: 14rem; }

/* Progress */
/* The grid takes the height left under the header, so the two-line footer stays on screen and the grid scrolls inside
   itself. The full-height pages (Progres, Log, Perubahan, Laporan) floor it at --fill-min-height (layout.css): below
   that the page scrolls instead (phones always; desktop only in a window under about 450px tall). DxGrid has no
   fill-height parameter: Dx docs size it through a CSS height constraint. */
.progress-page .progress-grid { flex: 1 1 0; min-height: var(--fill-min-height); }
/* Workaround for a DevExpress 26.1.5 Fluent theme bug: fixed footer cells (Fitur, Selesai) paint var(--dxbl-grid-footer-bg),
   which the theme sets transparent, so summaries of columns scrolled to the left show through them. Fixed header cells
   paint var(--dxbl-grid-bg); the footer gets the same opaque background (devexpress-blazor.md, section 5). */
.progress-page .progress-grid { --dxbl-grid-footer-bg: var(--dxbl-grid-bg); }
.progress-page td.pt-cell-pending { background-color: var(--dxds-color-surface-warning-subdued-rest); }
.progress-page td.pt-cell-done { background-color: var(--dxds-color-surface-success-subdued-rest); }
/* Aspect does not apply to the row's lingkup (aspect_scope): never a target, never clickable. */
.progress-page td.pt-cell-na { background-color: var(--dxds-color-surface-neutral-subdued-rest); }
.progress-page td.pt-cell-clickable { cursor: pointer; }
.progress-page td.pt-cell-clickable:hover { outline: 2px solid var(--dxds-color-border-neutral-default-rest); outline-offset: -2px; }
/* Toolbar template items (Per tanggal, read-only note): label and editor on one line, centred like the button items. */
.progress-toolbar-text { display: flex; align-items: center; gap: 0.5rem; height: 100%; white-space: nowrap; }
/* Per tanggal arrows (DxEditorButton): the theme greys editor buttons only when the whole editor is disabled, so an arrow
   disabled at the history start or today takes the theme's disabled button colour itself. The arrows also narrow the
   date box; on a phone the adaptive toolbar squeezed it until the date was cut, so the input keeps room for dd/MM/yyyy. */
.progress-toolbar-text .dxbl-text-edit-btn:disabled { color: var(--dxbl-btn-disabled-color); }
.progress-toolbar-text .dxbl-text-edit-input { min-width: 10ch; }
.progress-page tr.pt-row-unused > td { color: var(--dxds-color-content-neutral-subdued-rest); font-style: italic; }
/* Changed within 7 days up to the shown day (toolbar "Tandai perubahan 7 hari"). */
.progress-page td.pt-cell-changed { box-shadow: inset 0 0 0 2px var(--dxds-color-border-primary-default-rest); }
/* The cell's history button (timeline popup) sits at the cell's inline end, so the state icon stays centred. A mouse sees
   it on hover or keyboard focus; a cell with work notes (db/026) shows it always, which marks those cells. Touch screens
   have no hover and always show it. */
.progress-page td.pt-cell { position: relative; }
.progress-page .pt-cell-history { position: absolute; inset-block: 0; inset-inline-end: 0; display: flex; align-items: center; }
@media (hover: hover) {
    .progress-page .pt-cell-history:not(.pt-cell-history-noted) { visibility: hidden; }
    .progress-page td.pt-cell:hover .pt-cell-history, .progress-page td.pt-cell:focus-within .pt-cell-history { visibility: visible; }
}
.progress-page .pt-cell-history-noted { color: var(--dxds-color-content-primary-default-rest); }
.progress-page .progress-filter { flex: none; }
/* Not scoped to .progress-page: the filter row drop-down list renders outside the page element. */
.state-icon { display: inline-block; width: 1rem; height: 1rem; vertical-align: middle; }
.state-done { color: var(--dxds-color-content-success-default-rest); }
.state-pending { color: var(--dxds-color-content-warning-default-rest); }
.state-not-targeted { color: var(--dxds-color-content-neutral-subdued-rest); }
.state-option { display: inline-flex; align-items: center; gap: 0.5rem; }

/* Log: same full-height grid as Progress; a row click opens the detail popup. */
.log-page .log-grid { flex: 1 1 0; min-height: var(--fill-min-height); }
.log-page tr.log-row { cursor: pointer; }

/* Perubahan: same full-height grid as Log, under the period picker and the summary card. */
.changes-page .changes-summary { flex: none; }
.changes-page .changes-grid { flex: 1 1 0; min-height: var(--fill-min-height); }
/* Chart region (ChartRegion): the chart's Height, 21rem on a phone. */
.changes-chart { flex: none; min-height: 16rem; }
@media (max-width: 767px) { .changes-chart { min-height: 21rem; } }

/* Laporan: tabs Kalender and Ringkasan Teknis; the legend sits in the scheduler's toolbar; label colours come from the
   theme's utility palette. */
.reports-calendar { display: flex; flex-direction: column; gap: var(--page-gap); }
.reports-tab-content { padding-top: var(--page-gap); }
.reports-page .reports-scheduler { flex: 1 1 0; min-height: var(--fill-min-height); }
/* Month rows share the scheduler's height. DxScheduler sizes a week from its own minimum (CellMinHeight, theme variable
   --dxbl-scheduler-month-table-time-cell-height, 160px by default; busy days grow past it) and never stretches weeks to
   the height of the component, so a short window scrolled and a tall one left the rest empty. The scroll viewer of the
   cells is a size container, so 100cqh is its height: a week is a sixth of it (never under --dxds-spacing-600, 3.75rem).
   Always a sixth, not the real week count of the month: DevExpress places the appointments with the row heights of the
   moment, and a height that changes after render (a count read with :has, a table stretched with min-height) leaves them
   off their cells.
   The variable is set here, not with CellMinHeight, which writes an inline value that would win. */
.reports-scheduler dxbl-month-view dxbl-scroll-viewer { container-type: size; }
.reports-scheduler dxbl-month-view.dxbl-sc-month { --dxbl-scheduler-month-table-time-cell-height: max(var(--dxds-spacing-600), calc(100cqh / 6)); }
/* Desktop frame: the scheduler (or, in Ringkasan Teknis, the grid) takes the height left and scrolls inside itself. The
   chain down to it is flex: the page body, DxTabs (tabs-fill, layout.css) with its active content, the tab's own div and
   the calendar region. On a phone the day cards flow in the page area as before. */
@media (min-width: 769px) {
    .reports-page .reports-calendar { flex: 1 1 0; min-height: 0; }
    .reports-page .reports-tab-content { display: flex; flex-direction: column; flex: 1 1 0; min-height: 0; }
    .reports-page .reports-technical-grid { flex: 1 1 0; min-height: var(--fill-min-height); }
}
.reports-legend { display: flex; align-items: center; flex-wrap: wrap; gap: 0.25rem 1rem; height: 100%; padding: 0 0.5rem; color: var(--dxds-color-content-neutral-subdued-rest); font-size: var(--dxds-font-size-base-sm); }
.reports-legend-item { display: inline-flex; align-items: center; gap: 0.375rem; white-space: nowrap; }
.reports-legend-swatch { display: inline-block; width: 0.625rem; height: 0.625rem; border-radius: 0.125rem; }
.reports-label-report { background-color: var(--dxds-color-surface-utility-blue-default-rest); }
.reports-label-release { background-color: var(--dxds-color-surface-utility-green-default-rest); }
.reports-label-activity { background-color: var(--dxds-color-surface-utility-orange-default-rest); }
.reports-label-notes { background-color: var(--dxds-color-surface-utility-purple-default-rest); }
.reports-text { white-space: pre-line; overflow-wrap: anywhere; }
.reports-month { display: flex; align-items: center; height: 100%; padding: 0 0.5rem; font-weight: 600; }
/* Laporan on a phone: a day's report, release and change links hold sentences, so they wrap and start at the left.
   Fluent draws a Link button in ink; these take the app's link colour (primary blue, darker on hover). Two classes:
   the theme sets the colour on .dxbl-btn.dxbl-btn-link. */
.dxbl-btn.reports-day-link {
    white-space: normal; text-align: left; height: auto; padding-left: 0;
    --dxbl-btn-color: var(--dxds-color-content-primary-default-rest);
    --dxbl-btn-hover-color: var(--dxds-color-content-primary-default-hovered);
}

/* Catatan Rilis: the user changelog (one card per release) and, for admins, the Teknis tab with the commit grids. Plain
   text inside a form layout item does not wrap, so the text classes do. Desktop frame: the admin's tab list stays and the
   active tab's content scrolls (tabs-fill, Laporan); like the page body it spans the page area so shadows are not clipped.
   Without tabs (viewers) the page body scrolls. */
.release-notes-tab { padding-top: var(--page-gap); }
@media (min-width: 769px) {
    .release-notes-tab { flex: 1 1 0; margin-inline: calc(-1 * var(--page-gutter)); min-height: 0; overflow: auto; padding: var(--page-gap) var(--page-gutter); }
}
.release-notes-user { display: flex; flex-direction: column; gap: var(--page-gap); }
.release-notes-list { margin: 0; padding-left: 1.25rem; overflow-wrap: anywhere; }
.release-text { overflow-wrap: anywhere; }
.release-body { white-space: pre-line; overflow-wrap: anywhere; }
