/* PHNX dashboard — background gradient.
 *
 * Phase 3 (2026-08-29): settings.yaml now sets a `background:` wallpaper
 * (config/images/homepage_background.png), which homepage renders as a
 * full-bleed layer with its own dark scrim/blur/saturate/brightness — it
 * covers the viewport via background-size: cover, so this gradient is no
 * longer visible on the dashboard itself in normal use. Left in place
 * (unchanged, still dark/low-contrast for `theme: dark` / `color: slate`)
 * as the `body` fallback for states the wallpaper doesn't cover — e.g. the
 * OIDC sign-in page, or a page load before the background image resolves —
 * so nothing regresses to a lighter default if the image is ever missing.
 */
body {
  background: linear-gradient(135deg, #0b0f1a 0%, #131a2b 45%, #1b1330 100%) fixed;
  background-attachment: fixed;
  min-height: 100vh;
}

/* Phase 11 (2026-08-29): time under date, weather beside them.
 *
 * DEPENDS ON CHILD ORDER: widgets.yaml lists the two `datetime` widgets
 * (date, then time) before the single `openmeteo` widget, so
 * #information-widgets-right's children render in DOM order date(1st),
 * time(2nd), weather(3rd). The grid placement below is purely positional
 * (nth-child), not keyed to widget type — if widgets.yaml is ever
 * reordered (e.g. weather moved before the datetime widgets, or a second
 * openmeteo/search widget added to the right-aligned group), these rules
 * will silently place the wrong widget in the wrong cell. Re-check this
 * comment and the nth-child selectors below against widgets.yaml's actual
 * order any time that file changes.
 */
#information-widgets-right {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-rows: auto auto;
  column-gap: 0.75rem;
  row-gap: 0;
  /* Phase 11 Task 2: homepage's own markup gives this element Tailwind's
   * `justify-end`, which (as a flex/grid alignment) packs its content
   * against the far right of its box. Combined with `grow` (below) making
   * that box fill all of row one's remaining width, this is what created
   * the large empty gap between the logo and the date/time/weather cluster
   * that the operator asked to close — see the Task 2 interpretation note
   * further down. Overriding to `start` packs the grid against the LEFT
   * edge of its box instead, i.e. immediately after the logo, while the
   * grid itself still ends up the rightmost widget group in reading order.
   */
  justify-content: start;
}

#information-widgets-right > *:nth-child(1) {
  grid-column: 1;
  grid-row: 1;
}

#information-widgets-right > *:nth-child(2) {
  grid-column: 1;
  grid-row: 2;
}

#information-widgets-right > *:nth-child(3) {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
}

/* Phase 9 (2026-08-29): header restructuring — two rows instead of one.
 *
 * homepage renders left-aligned header widgets (logo, resources) in file
 * order inside #widgets-wrap, then appends a separate right-aligned
 * sub-container (#information-widgets-right) holding datetime/weather
 * widgets, as a LATER sibling of #widgets-wrap's own children. Flexbox
 * document order therefore puts logo, then the five resources widgets,
 * then the right-aligned date/time/weather group — which would put the
 * five stats on the top row, ahead of date/time/weather, the opposite of
 * what's wanted here.
 *
 * These `order` values (flex source order, not DOM order) put the logo and
 * the right-aligned group on row one, and push the five resources widgets
 * onto their own row two, by giving them the highest order value so they
 * wrap after the right-aligned group's `grow` has claimed the rest of row
 * one's width. This depends entirely on homepage's current DOM structure
 * (#widgets-wrap as a flex-wrap row, #information-widgets-right as its
 * last flex child) and these exact class/id names — a future homepage
 * upgrade that reshuffles the info-widgets markup could silently break
 * this. Unverified: whether logo + date/time/weather actually stay on one
 * row at narrow viewport widths, since #information-widgets-right's
 * `grow` combined with wrapping behavior here was not tested in a browser.
 *
 * Phase 11 (2026-08-29) Task 2 — interpretation note: the operator's
 * request ("keep the header items together... rather than being flung
 * apart") is implemented here as: `#widgets-wrap` no longer distributes
 * its row-one children (logo, date/time/weather group) to opposite ends
 * via `justify-between` — it now packs them together at the start, using
 * each widget's own existing Tailwind margin (from `headerStyle: clean`)
 * for spacing rather than adding a separate `gap`. The
 * #information-widgets-right box itself is UNCHANGED here — it still has
 * `grow` and still fills the rest of row one's width, because that's the
 * only mechanism keeping the five resources widgets on their own row two
 * (see the wrap-mechanism explanation above); removing `grow` would let
 * those five widgets flow back onto row one. Instead, the CONTENT inside
 * that box is packed to its left edge (`justify-content: start` above),
 * so it sits directly after the logo instead of flush against the outer
 * right edge — the empty space that used to sit between logo and cluster
 * now sits invisibly to the right of the weather widget instead. This is
 * ONE valid reading of an ambiguous request; if "kept together" was meant
 * literally as "same total width as the card grid, no trailing gap
 * either," a different, more invasive fix (removing `grow` and forcing
 * the row-two wrap some other way, e.g. a flex-basis:100% spacer) would
 * be needed instead — flag this back if the rendered header still looks
 * wrong.
 */
/* Phase 13 (2026-08-30): the `.information-widget-resources` selector that
 * used to sit below for the five header stats (order + spacing) was always
 * dead — see the corrected rule and comment further down for why, and for
 * the `:has()`-based replacement. The `order` mechanism and DOM-structure
 * description in the comment above (logo + #information-widgets-right on
 * row one, resources widgets pushed to row two) are otherwise still
 * accurate; only the selector reaching the resources widgets was wrong.
 */
#widgets-wrap {
  justify-content: flex-start;
}

.information-widget-logo {
  order: 0;
}

#information-widgets-right {
  order: 1;
}

/* Phase 13 (2026-08-30): corrected selector for the five header stat
 * widgets (CPU/memory/disk/uptime/network from widgets.yaml's `resources:`
 * blocks).
 *
 * Verified against homepage v2.1.2 source (github.com/gethomepage/homepage),
 * not inferred: `src/components/widgets/resources/resources.jsx` — the
 * component `widgets.yaml`'s `resources:` type actually renders — calls
 * `<Container options={options}>` with NO `additionalClassNames`, so its
 * wrapper `<div>` (the flex item that is a direct child of `#widgets-wrap`)
 * carries no class of its own; `getAllClasses()` in `widget/container.jsx`
 * only adds whatever `additionalClassNames` string it's given, which here
 * is empty. The plural class `.information-widget-resources` is produced
 * only by the DIFFERENT, unrelated `src/components/widgets/widget/
 * resources.jsx` (`classNames("information-widget-resources",
 * additionalClassNames)`), which is used solely by the `glances` info
 * widget — not in use on this deployment (see `widgets.yaml`). The rules
 * that used to sit here (`order: 2; flex: 0 0 auto;` targeting
 * `.information-widget-resources`) therefore never matched anything and
 * never applied, since Phase 9/11 — the same dead selector `config/
 * custom.js` independently hit and documented while building the GPU
 * header hack.
 *
 * Each individual stat inside a resources widget DOES render
 * `.information-widget-resource` (SINGULAR — `src/components/widgets/
 * widget/resource.jsx`, used by `resources/cpu.jsx` etc.), but that's the
 * value/label pair itself, nested one level below the actual flex item
 * `#widgets-wrap` lays out — the real flex item is the Container `<div>`
 * that *contains* it (one `.information-widget-resource` descendant per
 * `resources:` block, since each block here sets only one stat flag). CSS
 * has no "select an ancestor by its descendant" combinator other than
 * `:has()`, so that's what reaches it: `#widgets-wrap > *:has(.information-
 * widget-resource)` selects exactly the direct children of `#widgets-wrap`
 * that contain a `.information-widget-resource` anywhere inside them — the
 * five resources Container divs, and nothing else (the logo and
 * `#information-widgets-right` don't contain that class).
 *
 * `:has()` support: shipped in current Chrome, Edge, Safari and Firefox.
 * In a browser old enough to lack it, this rule simply won't match
 * anything — no error, the layout just falls back to unstyled document
 * order — an acceptable graceful degradation, not a failure mode.
 *
 * Intent preserved from Phase 9/11: `order: 2` still pushes these onto
 * their own row, after the logo (order 0) and `#information-widgets-right`
 * (order 1) claim row one. `flex: 0 0 auto` still sizes each stat to its
 * own content rather than stretching it to an equal share of the row
 * (edge-to-edge) — spacing between them comes from each widget's own
 * existing Tailwind margin (`headerStyle: clean` gives every header widget
 * m-5/sm:m-9), combined with `#widgets-wrap`'s `justify-content:
 * flex-start` above, which stops them being distributed with
 * space-between across the full row width.
 */
#widgets-wrap > *:has(.information-widget-resource) {
  order: 2;
  flex: 0 0 auto;
}

/* openmeteo (weather) has no `text_size` option in homepage's schema, so
 * matching it to the `text_size: sm` set on the two datetime widgets has
 * to happen in CSS. Scoped to #information-widgets-right so it only
 * touches the right-aligned date/time/weather group in the header, never
 * service-card text elsewhere on the page. Unverified: the exact selector
 * openmeteo renders its text with may differ from a plain descendant
 * match if homepage wraps its value in nested spans with their own
 * sizing — if the font doesn't visibly shrink, inspect the live DOM for
 * the weather widget's actual text element and tighten this selector.
 * Class name verified against homepage v2.1.2 source: openmeteo.jsx renders
 * `information-widget-openmeteo` (NOT `-weather`, which matches nothing).
 */
#information-widgets-right .information-widget-openmeteo,
#information-widgets-right .information-widget-openmeteo * {
  font-size: 0.875rem; /* matches Tailwind's `sm` used by text_size: sm */
  line-height: 1.25rem;
}

/* Phase 10 (2026-08-29): stop service-widget stat labels wrapping.
 *
 * homepage's block.jsx (src/components/services/widget/block.jsx) renders
 * each stat block the same way for every widget type:
 *   <div class="... service-block">
 *     <div class="font-thin text-sm">VALUE</div>
 *     <div class="font-bold text-xs uppercase">LABEL</div>
 *   </div>
 * `.service-block` is a class this component adds itself (not a generic
 * Tailwind utility), so it's a reasonably stable hook — but a future
 * homepage upgrade that renames or restructures block.jsx could still
 * break this selector; if labels wrap again after an upgrade, that's the
 * first place to check. The label is targeted as the last-child div of
 * `.service-block` since it has no class of its own to hang a selector on.
 *
 * Multi-word labels like "ALERTS TRIGGERED" (16 chars, the longest in use)
 * were wrapping to two lines at the default text-xs (0.75rem) size inside
 * the narrow flex-1 block. Forcing nowrap alone would just push those
 * labels past the edge of their box, so the label is also shrunk to
 * ~0.625rem and `.service-block`'s horizontal padding is trimmed slightly
 * to reclaim a little extra width for the single line to fit into. The
 * value line (font-thin text-sm) is left untouched — it's short and never
 * wrapped.
 *
 * Trade-off: nowrap turns "wraps to two lines" into "overflows the box"
 * for any label still too wide after this. `overflow: hidden` is
 * deliberately NOT added here — it would silently truncate a label (e.g.
 * clip "ALERTS TRIGGERED" down to a fragment) rather than letting an
 * oversized label visibly overflow, and a truncated label reading as
 * something else entirely is a worse failure than an overflow that's
 * obviously wrong. This is a judgement call, not a guarantee: at narrow
 * viewport widths .service-block can still be narrower than these sizes
 * assume, and the longest labels may still not fit even after this change.
 * Unverified — neither of us can see the rendered page — whether
 * "ALERTS TRIGGERED" and "PULL REQUESTS" now sit on one line without
 * spilling outside their box; check those two specifically after reload.
 */
.service-block {
  padding-left: 0.25rem;
  padding-right: 0.25rem;
}

.service-block > div:last-child {
  white-space: nowrap;
  font-size: 0.625rem;
  line-height: 0.875rem;
}

/* Darker card tint.
 *
 * `cardBlur` in settings.yaml only controls the BLUR RADIUS behind a card —
 * it has no colour component. The tint comes from Tailwind classes on the
 * card element itself: homepage renders `.service-card` with
 * `bg-theme-100/20 dark:bg-white/5`, i.e. white at 5% opacity in dark mode,
 * which reads very light over a wallpaper.
 *
 * Overriding with a dark translucent fill keeps the frosted-glass effect
 * (the backdrop-blur still applies) while making card text far more legible
 * over a busy background. !important is needed because Tailwind's dark
 * variant compiles to a higher-specificity selector than a bare class.
 *
 * Adjust the alpha values to taste: higher = darker/more opaque, lower =
 * more wallpaper showing through. `.service-card` comes from homepage's own
 * item.jsx, so an upgrade renaming it would silently drop this styling.
 */
.service-card {
  background-color: rgba(0, 0, 0, 0.5) !important;
}

.service-card:hover {
  background-color: rgba(0, 0, 0, 0.62) !important;
}

/* Phase 11 (2026-08-29) Task 3: enlarge the header logo.
 *
 * homepage's logo.jsx hard-codes the <img> at width={48} height={48} —
 * these compile to HTML width/height attributes, which browsers treat as
 * presentational hints with specificity roughly equal to a UA stylesheet,
 * so a plain CSS rule alone may not reliably win; !important forces it.
 * The wrapping `.information-widget-logo > .resolved` div carries no
 * explicit size of its own (only an `mr-3` margin per the verified
 * source), so it sizes to its child and should grow with the enlarged
 * image rather than clipping it — `overflow: visible` on both is added
 * as a guard in case a homepage upgrade adds a fixed box there. Sized to
 * 80px (~1.67x the original 48px) per the operator's "roughly 80x80"
 * request. `align-self: center` keeps it vertically aligned with the
 * rest of row one now that it's noticeably taller than the date/time/
 * weather text beside it. Unverified — cannot see the rendered page —
 * whether 80px reads as proportionate next to the five (unchanged-size)
 * resources widgets on row two beneath it.
 */
.information-widget-logo,
.information-widget-logo .resolved {
  overflow: visible;
}

.information-widget-logo {
  align-self: center;
}

.information-widget-logo img {
  width: 80px !important;
  height: 80px !important;
  max-width: none;
  max-height: none;
}
