a2d1ed935d
- Promote .fc-section-h to a global token (app.css). It was copied identically into 4 cards, and TranslationCard used the class with NO local def — so its section headers rendered unstyled. Now fixed everywhere. - Promote .fc-good / .fc-weak status colours to globals; delete the local copies in the GPU/heads cards. (.fc-ok stays local — divergent: on-surface in HeadsCard vs success in QueuesTable. .fc-bad stays — different name.) - Delete 10 identical local .fc-muted redefinitions that crept back after the 2026-06-09 sweep; the global utility already covers them. - DbMaintenanceCard: opacity:0.6 muted text → the .fc-muted token (the exact anti-pattern that token's comment forbids). - HeadsCard: collapse byte-identical ratePct() into pct(). CSS-only + one template class swap; no logic change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsmJSQxnNxGgtM5Yz4GAqi
130 lines
7.2 KiB
CSS
130 lines
7.2 KiB
CSS
/* App-global overrides. Imported in main.js after 'vuetify/styles', but
|
||
Vite's production bundler reorders CSS chunks so source order is not a
|
||
reliable winner against node_modules CSS at equal specificity. Rules
|
||
here either out-specify Vuetify's default or use !important on the
|
||
exact properties that need to win. */
|
||
|
||
/* Tooltip readability fix (operator-flagged 2026-05-28).
|
||
Vuetify's default v-tooltip pairs `on-surface-variant` TEXT with an
|
||
`surface-variant` BACKGROUND. FC's theme deliberately maps
|
||
`on-surface-variant` to vellum (#C2BFB4 — a light cream, correct for
|
||
muted captions/hints on the dark page) but never defines
|
||
`surface-variant`, so Vuetify auto-generates a light-ish background:
|
||
light text on light bg → near-white-on-near-white, unreadable.
|
||
|
||
Tooltips want the inverse of muted body text — a dark, slightly
|
||
elevated panel with the HIGH-contrast parchment text. Fixing it here
|
||
(not by changing on-surface-variant) keeps captions/empty-states
|
||
correct while making every tooltip in the app legible.
|
||
|
||
`!important` on the contrast properties: this rule ties Vuetify's
|
||
default at specificity (.v-tooltip > .v-overlay__content), and in a
|
||
Vite production build the node_modules CSS can land after app.css in
|
||
the final stylesheet regardless of import order, so source-order wins
|
||
aren't reliable. !important removes that fragility for the two
|
||
properties whose drift made tooltips unreadable; the cosmetic border
|
||
and shadow don't need it (Vuetify doesn't set them). Operator
|
||
re-flagged 2026-05-29 on the deployed :latest after PR #33. */
|
||
.v-tooltip > .v-overlay__content {
|
||
background: rgb(var(--v-theme-surface-bright)) !important; /* slate #2C313A */
|
||
color: rgb(var(--v-theme-on-surface)) !important; /* parchment #E8E4D8 */
|
||
border: 1px solid rgb(var(--v-theme-on-surface-variant) / 0.25);
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
|
||
}
|
||
|
||
/* Canonical muted/secondary text token (DRY pattern sweep 2026-06-09).
|
||
Was redefined identically in 12 component <style scoped> blocks; now one
|
||
global utility. Muted text uses the explicit on-surface-variant (vellum)
|
||
token, NOT opacity — Vuetify's text-medium-emphasis is opacity-based and is
|
||
deliberately not used here. `.fc-muted` is a custom class Vuetify never
|
||
emits, so no specificity/reorder fight — no !important needed. */
|
||
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
|
||
|
||
/* Section sub-heading in settings cards (DRY pass #161): was redefined
|
||
identically in 4 cards, and TranslationCard used the class with NO local def
|
||
so its section headers rendered unstyled. Now one global utility. */
|
||
.fc-section-h {
|
||
font-size: 13px; font-weight: 700; letter-spacing: 0.03em;
|
||
text-transform: uppercase; color: rgb(var(--v-theme-on-surface));
|
||
}
|
||
|
||
/* Status text colours (DRY pass #161): fc-good = success, fc-weak = error,
|
||
consolidated from the GPU / heads cards. fc-ok is intentionally NOT global —
|
||
it means on-surface in HeadsCard but success in QueuesTable. */
|
||
.fc-good { color: rgb(var(--v-theme-success)); }
|
||
.fc-weak { color: rgb(var(--v-theme-error)); }
|
||
|
||
/* Vuetify 4 dropped its global CSS reset (normalisation moved into each
|
||
component). FC's layouts assumed the reset zeroed margins on text elements, so
|
||
restore just that — the "minimal reset" from the v4 upgrade guide — inside
|
||
Vuetify's own reset layer, which is low precedence so component + app styles
|
||
still win over it. Batch-4 Vuetify 3→4 (#1449). */
|
||
@layer vuetify-core.reset {
|
||
ul, ol, figure, details, summary { padding: 0; margin: 0; }
|
||
h1, h2, h3, h4, h5, h6, p { margin: 0; }
|
||
}
|
||
|
||
/* Active-tab indicator (operator-flagged 2026-07-13 in the Vuetify-4 review): v4's
|
||
MD3 v-tab "slider" underline renders wider than the tab and floats below it. The
|
||
active tab's TEXT is already accent-coloured (color="accent"), so drop the slider
|
||
and mark the active tab with a subtle accent fill + rounded top — a clean,
|
||
unambiguous highlight app-wide (Subscriptions / Browse / Settings / Series). */
|
||
.v-tab__slider { display: none !important; }
|
||
.v-tab[aria-selected="true"],
|
||
.v-tab.v-tab--selected {
|
||
background: rgb(var(--v-theme-accent) / 0.12);
|
||
border-radius: 8px 8px 0 0;
|
||
}
|
||
|
||
/* --- Continuous chrome fade (operator-asked 2026-07-13: "group the sub-nav as
|
||
part of the nav and use a single gradient in them"). ------------------------
|
||
The TopNav and any sticky sub-header pinned directly beneath it (Gallery's
|
||
filter bar, the Browse/Series/Settings/Subscriptions tabs bars) used to each
|
||
paint their OWN dark-to-transparent gradient (or a solid band), so the fade
|
||
read as happening TWICE — dark, fade out, then dark again. Instead the two
|
||
share ONE obsidian fade: the nav paints the TOP half (opaque → the seam
|
||
alpha) and the sub-header paints the CONTINUATION (seam alpha → transparent)
|
||
over its own height. Both reference --fc-chrome-seam, so the alphas meet
|
||
exactly at the 64px boundary — no re-darkening, no doubling, one gradient.
|
||
|
||
--fc-chrome-seam is the single knob: raise it for a heavier sub-header (more
|
||
legible tabs/controls over scrolling content), lower it for a lighter fade. */
|
||
:root {
|
||
--fc-chrome-rgb: 20, 23, 26; /* obsidian #14171A — matches the TopNav */
|
||
/* Alpha where the nav hands off to the sub-header — also the "hold" level of
|
||
the fade. The chrome stays fairly opaque (0.92 → this) through the bulk of
|
||
its height, then drops to transparent in a small eased section at the very
|
||
bottom (see the multi-stop gradients), so it reads as a slow falloff that
|
||
tails off softly rather than a straight line to a hard edge (operator
|
||
2026-07-13). Raise for heavier/more-legible chrome, lower for a lighter fade. */
|
||
--fc-chrome-seam: 0.68;
|
||
/* Actual TopNav height, measured live (ResizeObserver in TopNav.vue) and used
|
||
by full-height workspaces (Explore/Subscriptions: calc(100vh - var)) and by
|
||
every sticky sub-header pinned beneath the nav (top: var). This was a
|
||
hardcoded 64px in ~6 places; Vuetify 4's MD3 sizing made the real nav a
|
||
different height, so the Explore workspace overflowed and its breadcrumb
|
||
tucked under the nav (#1481). This fallback is only used pre-measure. */
|
||
--fc-nav-h: 64px;
|
||
}
|
||
/* Applied to a sticky sub-header so it continues the nav's fade instead of
|
||
restarting it. Percentage stops so the fade always spans the element's height
|
||
(survives the filter bar's expanding refine panel). The blur keeps tabs and
|
||
controls legible as the fill thins toward transparent — the solid-surface
|
||
bars it replaces had none, so it must live here. */
|
||
.fc-chrome-continues {
|
||
/* Continues the nav's fade: HOLDS near the seam alpha through the first ~55%
|
||
(subtle), then eases down to transparent over the last ~45% with an
|
||
intermediate stop so the tail is soft — no hard line at the bottom edge
|
||
(operator 2026-07-13). Percentage stops keep the shape spanning the
|
||
element's height (survives the filter bar's expanding refine panel). */
|
||
background: linear-gradient(
|
||
to bottom,
|
||
rgba(var(--fc-chrome-rgb), var(--fc-chrome-seam)) 0%,
|
||
rgba(var(--fc-chrome-rgb), 0.60) 55%,
|
||
rgba(var(--fc-chrome-rgb), 0.28) 82%,
|
||
rgba(var(--fc-chrome-rgb), 0) 100%
|
||
);
|
||
backdrop-filter: blur(2px);
|
||
-webkit-backdrop-filter: blur(2px);
|
||
}
|