// ============================================================================= // Styles specific to PlanningPage — colocated next to PlanningPage.tsx since // nothing else uses these classes. Ported from the reviewed HTML mockup // (see the plan file / PR description) onto the app's real design tokens — // no light/dark duplication needed here, unlike the standalone mockup: // every `var(--color-*)` below already resolves per-theme globally (see // styles/_theme.scss). // ============================================================================= // `.app-content` (AppLayout.scss) already stretches to the full viewport // height (flex item of `.app-layout`, itself `min-height: 100vh` — the // same stretch the sidebar relies on to pin its footer at the bottom). // `.planning-page` just needs to fill that box and lay out as a column so // `.planning-grid-wrapper` can grow to fill whatever's left under the // header, instead of the grid being only as tall as its content. .planning-page { height: 100%; display: flex; flex-direction: column; &__header { flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-md); margin-bottom: var(--space-lg); } &__status { color: var(--color-text-muted); font-size: var(--font-size-md); } &__status--error { color: var(--color-error); } } // --- The grid itself -------------------------------------------------------- // (Week navigator + calendar popover styles now live in // features/planning/week-navigator.scss, imported by WeekNavigator.tsx // directly — extracted once ShoppingListPage started reusing that // component too.) .planning-grid-wrapper { flex: 1; min-height: 0; overflow: auto; background: var(--color-surface); border-radius: var(--radius-md); box-shadow: var(--shadow-sm); } table.planning-grid { width: 100%; height: 100%; min-width: 62rem; border-collapse: collapse; table-layout: fixed; th, td { border: 1px solid var(--color-border); vertical-align: top; } thead th { padding: var(--space-sm) var(--space-md); background: var(--color-surface-alt); text-align: left; &:first-child { width: 9rem; } .day-name { display: block; font-size: var(--font-size-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); font-weight: 600; } .day-date { display: block; font-size: var(--font-size-md); font-weight: 700; margin-top: 2px; color: var(--color-text); } &.today { background: color-mix(in srgb, var(--color-primary) 10%, var(--color-surface-alt)); .day-date { color: var(--color-primary); } } } tbody th { padding: var(--space-sm) var(--space-md); background: var(--color-surface-alt); text-align: center; vertical-align: middle; font-size: var(--font-size-sm); font-weight: 600; } td.today { background: color-mix(in srgb, var(--color-primary) 4%, var(--color-surface)); } // Repas groupés par moment de la journée (Matin / Midi / Après-midi / // Soir) — piloté uniquement via `border-bottom` (jamais `border-top`) : // avec `border-collapse: collapse`, deux bordures différentes qui se // rencontrent sur la même arête peuvent fusionner de façon ambiguë selon // le navigateur — en désactivant `border-top` sur tbody, chaque arête // horizontale n'est plus définie que d'un seul côté, sans ambiguïté // possible. Toutes les séparations entre repas sont pleines (même couleur // que les séparations de jour) ; seule la frontière entre deux groupes // ("band-end", la dernière ligne d'un groupe) se distingue par une // épaisseur plus marquée. tbody th, tbody td { border-top: none; border-bottom: 1px solid var(--color-border); } tbody tr.band-end th, tbody tr.band-end td { border-bottom: 2px solid var(--color-border); } } // --- Case : pastilles de recette + bouton "+" ------------------------------- .meal-cell { padding: var(--space-sm); } .meal-cell__content { display: flex; flex-direction: column; gap: var(--space-xs); height: 100%; } .meal-cell__recipes { display: flex; flex-direction: column; gap: var(--space-xs); } .recipe-chip { display: flex; align-items: center; gap: var(--space-xs); width: 100%; box-sizing: border-box; padding: 0.3rem var(--space-sm); border-radius: var(--radius-pill); background: var(--color-tag); color: var(--color-tag-ink); font-size: var(--font-size-xs); font-weight: 600; &__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } &__remove { flex-shrink: 0; width: 1rem; height: 1rem; display: grid; place-items: center; border: none; background: none; cursor: pointer; color: inherit; opacity: 0; font-size: 0.65rem; border-radius: 50%; } &:hover &__remove { opacity: 0.7; } &__remove:hover { opacity: 1; background: rgba(0, 0, 0, 0.15); } } // Pleine largeur, sans bordure (juste un fond au survol — plus épuré qu'un // contour pointillé), et toujours collé en haut de la case (juste sous la // dernière recette s'il y en a), jamais centré au milieu d'une case vide. .add-recipe-btn { width: 100%; box-sizing: border-box; padding: 0.35rem; display: flex; align-items: center; justify-content: center; border: none; border-radius: var(--radius-base); background: none; color: var(--color-text-muted); font-size: var(--font-size-base); line-height: 1; cursor: pointer; &:hover { color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 8%, transparent); } }