mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
702 lines
13 KiB
CSS
702 lines
13 KiB
CSS
/*
|
|
* Print copies (components/print/print-root.tsx). A page that can print
|
|
* renders its copy into <body> next to the app; in print media the copy
|
|
* replaces everything else there, so the nav rail, sidebars, toolbars, open
|
|
* menus, toasts and plugin UI never reach the paper, and nothing is clipped
|
|
* by the app's fixed heights or scroll containers.
|
|
*
|
|
* The copy is always black on white with thin grey rules, whatever theme the
|
|
* app is in, and uses logical properties so right-to-left pages mirror.
|
|
* Millimetre sizes match lib/calendar-print.ts.
|
|
*/
|
|
|
|
[data-print-root] {
|
|
display: none;
|
|
}
|
|
|
|
@media print {
|
|
/* The theme sets color-scheme inline on <html>; a dark one paints the
|
|
page margins dark. */
|
|
html:has(> body > [data-print-root]) {
|
|
color-scheme: light !important;
|
|
background: #fff !important;
|
|
}
|
|
|
|
body:has(> [data-print-root]) {
|
|
height: auto !important;
|
|
min-height: 0 !important;
|
|
overflow: visible !important;
|
|
background: #fff !important;
|
|
color: #111 !important;
|
|
}
|
|
|
|
body:has(> [data-print-root]) > :not([data-print-root]) {
|
|
display: none !important;
|
|
}
|
|
|
|
[data-print-root] {
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
.pr-root {
|
|
/* Landscape page area of the smaller of A4 and Letter, 12 mm margins. */
|
|
--pr-page-h: 184mm;
|
|
--pr-ink: #111;
|
|
--pr-muted: #555;
|
|
--pr-faint: #8a8a8a;
|
|
--pr-rule: #bdbdbd;
|
|
--pr-rule-light: #e2e2e2;
|
|
--pr-shade: #f4f4f4;
|
|
color: var(--pr-ink);
|
|
background: #fff;
|
|
font-family: var(--font-sans, system-ui, sans-serif);
|
|
font-size: 10pt;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
/* The copy declares its orientation with @page size, which browsers apply
|
|
whatever the dialog's paper says; an orientation media query, though,
|
|
follows the dialog. So the page height goes by the declared one. */
|
|
.pr-root[data-orientation="portrait"] {
|
|
--pr-page-h: 253mm;
|
|
}
|
|
|
|
.pr-root *,
|
|
.pr-root *::before,
|
|
.pr-root *::after {
|
|
border-color: var(--pr-rule);
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.pr-root a {
|
|
color: inherit;
|
|
text-decoration: none;
|
|
}
|
|
|
|
/* ---- Header on every calendar printout and list -------------------------- */
|
|
|
|
.pr-header {
|
|
margin-bottom: 3mm;
|
|
padding-bottom: 2mm;
|
|
border-bottom: 0.3mm solid var(--pr-rule);
|
|
break-after: avoid;
|
|
}
|
|
|
|
.pr-page > .pr-header {
|
|
height: 15mm;
|
|
flex: none;
|
|
overflow: hidden;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.pr-title {
|
|
margin: 0;
|
|
font-size: 15pt;
|
|
font-weight: 600;
|
|
line-height: 1.25;
|
|
}
|
|
|
|
.pr-meta {
|
|
margin: 0.5mm 0 0;
|
|
color: var(--pr-muted);
|
|
font-size: 8.5pt;
|
|
}
|
|
|
|
.pr-page .pr-meta {
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.pr-meta-sep {
|
|
margin-inline: 2mm;
|
|
color: var(--pr-faint);
|
|
}
|
|
|
|
/* A view that fills exactly one sheet (month, week, day). */
|
|
.pr-page {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: var(--pr-page-h);
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* ---- Event chips --------------------------------------------------------- */
|
|
|
|
/* The calendar colour as a bar at the start, a light tint of it behind dark
|
|
text: readable in colour and in greyscale. The bar is a background stripe
|
|
over a transparent border: a coloured border on a rounded box would curve
|
|
on its inner edge too, the stripe is only rounded on the outside. */
|
|
.pr-chip {
|
|
--chip: #3b82f6;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
color: var(--pr-ink);
|
|
border-inline-start: 0.9mm solid transparent;
|
|
border-radius: 0.6mm;
|
|
background-color: color-mix(in srgb, var(--chip) 15%, #fff);
|
|
background-image: linear-gradient(var(--chip), var(--chip));
|
|
background-origin: border-box;
|
|
background-position: left top;
|
|
background-repeat: no-repeat;
|
|
background-size: 0.9mm 100%;
|
|
print-color-adjust: exact;
|
|
-webkit-print-color-adjust: exact;
|
|
}
|
|
|
|
[dir="rtl"] .pr-chip {
|
|
background-position: right top;
|
|
}
|
|
|
|
.pr-chip.is-timed {
|
|
background-color: #fff;
|
|
}
|
|
|
|
.pr-chip.is-inactive {
|
|
background-color: #fff;
|
|
color: var(--pr-muted);
|
|
}
|
|
|
|
.pr-chip.is-cancelled .pr-chip-title {
|
|
text-decoration: line-through;
|
|
}
|
|
|
|
.pr-chip.continues-before {
|
|
border-start-start-radius: 0;
|
|
border-end-start-radius: 0;
|
|
}
|
|
|
|
.pr-chip.continues-after {
|
|
border-start-end-radius: 0;
|
|
border-end-end-radius: 0;
|
|
}
|
|
|
|
.pr-chip-time {
|
|
flex: none;
|
|
font-variant-numeric: tabular-nums;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.pr-chip-title {
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* One-line chips: the title keeps its own direction (it is a <bdi>), so in
|
|
a right-to-left page an English title is still cut at its own end. */
|
|
.pr-lane-item > .pr-chip,
|
|
.pr-tg-event.is-compact > .pr-chip {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.8mm;
|
|
}
|
|
|
|
.pr-lane-item .pr-chip-title,
|
|
.pr-tg-event.is-compact .pr-chip-title {
|
|
flex: 0 1 auto;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* ---- Month --------------------------------------------------------------- */
|
|
|
|
.pr-month {
|
|
flex: 1;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
border: 0.25mm solid var(--pr-rule);
|
|
border-top: 0;
|
|
}
|
|
|
|
.pr-weekdays {
|
|
display: grid;
|
|
flex: none;
|
|
height: 6mm;
|
|
border-bottom: 0.25mm solid var(--pr-rule);
|
|
}
|
|
|
|
.pr-weekday {
|
|
align-self: end;
|
|
padding-bottom: 1mm;
|
|
text-align: center;
|
|
color: var(--pr-muted);
|
|
font-size: 7.5pt;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
}
|
|
|
|
.pr-month-week {
|
|
position: relative;
|
|
flex: 1 1 0;
|
|
min-height: 0;
|
|
display: grid;
|
|
border-top: 0.25mm solid var(--pr-rule);
|
|
}
|
|
|
|
.pr-month-week:first-of-type {
|
|
border-top: 0;
|
|
}
|
|
|
|
.pr-month-day {
|
|
min-width: 0;
|
|
padding: 0.6mm 1mm 0;
|
|
border-inline-start: 0.25mm solid var(--pr-rule-light);
|
|
}
|
|
|
|
.pr-month-day:first-child {
|
|
border-inline-start: 0;
|
|
}
|
|
|
|
.pr-month-day.is-outside {
|
|
background: var(--pr-shade);
|
|
print-color-adjust: exact;
|
|
-webkit-print-color-adjust: exact;
|
|
}
|
|
|
|
.pr-day-num {
|
|
height: 4.4mm;
|
|
font-size: 8pt;
|
|
font-weight: 600;
|
|
line-height: 4.4mm;
|
|
}
|
|
|
|
.pr-month-day.is-outside .pr-day-num {
|
|
color: var(--pr-faint);
|
|
font-weight: 400;
|
|
}
|
|
|
|
.pr-day-month {
|
|
margin-inline-end: 1mm;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.pr-lanes {
|
|
position: absolute;
|
|
inset-inline: 0;
|
|
top: 5mm;
|
|
bottom: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.pr-lane-item {
|
|
position: absolute;
|
|
height: 3.6mm;
|
|
padding-inline: 0.4mm;
|
|
font-size: 7pt;
|
|
line-height: 3.6mm;
|
|
}
|
|
|
|
.pr-lane-item > .pr-chip {
|
|
height: 100%;
|
|
padding-inline: 0.8mm;
|
|
}
|
|
|
|
.pr-more {
|
|
padding-inline: 1.2mm;
|
|
color: var(--pr-muted);
|
|
font-weight: 600;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* ---- Week and day: the time grid ----------------------------------------- */
|
|
|
|
.pr-tg {
|
|
flex: 1;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
border: 0.25mm solid var(--pr-rule);
|
|
border-top: 0;
|
|
}
|
|
|
|
.pr-tg-row {
|
|
display: grid;
|
|
flex: none;
|
|
}
|
|
|
|
.pr-tg-dayhead {
|
|
height: 9mm;
|
|
min-width: 0;
|
|
padding: 1mm 0.8mm;
|
|
text-align: center;
|
|
border-inline-start: 0.25mm solid var(--pr-rule-light);
|
|
border-bottom: 0.25mm solid var(--pr-rule);
|
|
}
|
|
|
|
.pr-tg-weekday {
|
|
color: var(--pr-muted);
|
|
font-size: 7.5pt;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
}
|
|
|
|
.pr-tg-date {
|
|
font-size: 11pt;
|
|
font-weight: 600;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.pr-tg-gutter-head,
|
|
.pr-tg-gutter {
|
|
border-bottom: 0.25mm solid var(--pr-rule);
|
|
}
|
|
|
|
.pr-tg-allday-label {
|
|
padding: 0.6mm 1mm;
|
|
color: var(--pr-muted);
|
|
font-size: 6.5pt;
|
|
text-align: end;
|
|
border-bottom: 0.25mm solid var(--pr-rule);
|
|
}
|
|
|
|
.pr-tg-allday {
|
|
position: relative;
|
|
border-inline-start: 0.25mm solid var(--pr-rule-light);
|
|
border-bottom: 0.25mm solid var(--pr-rule);
|
|
}
|
|
|
|
.pr-tg-body {
|
|
position: relative;
|
|
flex: 1;
|
|
min-height: 0;
|
|
display: grid;
|
|
}
|
|
|
|
.pr-tg-hours {
|
|
position: relative;
|
|
}
|
|
|
|
.pr-tg-hour-label {
|
|
position: absolute;
|
|
inset-inline-end: 1mm;
|
|
transform: translateY(-50%);
|
|
color: var(--pr-muted);
|
|
font-size: 6.5pt;
|
|
font-variant-numeric: tabular-nums;
|
|
line-height: 1;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.pr-tg-hour-label.is-first {
|
|
transform: none;
|
|
margin-top: 0.6mm;
|
|
}
|
|
|
|
.pr-tg-col {
|
|
position: relative;
|
|
min-width: 0;
|
|
border-inline-start: 0.25mm solid var(--pr-rule-light);
|
|
}
|
|
|
|
.pr-tg-line {
|
|
position: absolute;
|
|
inset-inline: 0;
|
|
border-top: 0.2mm solid var(--pr-rule-light);
|
|
}
|
|
|
|
.pr-tg-line.is-half {
|
|
border-top-style: dotted;
|
|
}
|
|
|
|
.pr-tg-event {
|
|
position: absolute;
|
|
min-height: 3.2mm;
|
|
padding: 0.15mm 0.3mm;
|
|
}
|
|
|
|
.pr-tg-event > .pr-chip {
|
|
display: block;
|
|
height: 100%;
|
|
padding: 0.3mm 0.8mm;
|
|
font-size: 6.8pt;
|
|
line-height: 1.2;
|
|
white-space: normal;
|
|
}
|
|
|
|
.pr-tg-event .pr-chip-time {
|
|
display: block;
|
|
font-weight: 400;
|
|
color: var(--pr-muted);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.pr-tg-event .pr-chip-title {
|
|
display: block;
|
|
font-weight: 600;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
/* Too short for two lines: start and title on one. */
|
|
.pr-tg-event.is-compact > .pr-chip {
|
|
padding-block: 0;
|
|
white-space: nowrap;
|
|
line-height: 2.9mm;
|
|
}
|
|
|
|
.pr-tg-event.is-compact .pr-chip-time {
|
|
color: var(--pr-ink);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.pr-tg-event .pr-chip-where {
|
|
display: block;
|
|
color: var(--pr-muted);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
/* ---- Agenda, tasks, contact lists: flowing lists ------------------------- */
|
|
|
|
.pr-keep {
|
|
break-inside: avoid;
|
|
}
|
|
|
|
.pr-day-heading {
|
|
margin: 4mm 0 0;
|
|
padding-bottom: 1mm;
|
|
border-bottom: 0.3mm solid var(--pr-rule);
|
|
font-size: 10.5pt;
|
|
font-weight: 600;
|
|
break-after: avoid;
|
|
}
|
|
|
|
.pr-list-row {
|
|
display: grid;
|
|
gap: 3mm;
|
|
padding-block: 1.3mm;
|
|
border-bottom: 0.2mm solid var(--pr-rule-light);
|
|
break-inside: avoid;
|
|
}
|
|
|
|
.pr-agenda-row {
|
|
grid-template-columns: 30mm minmax(0, 1fr);
|
|
}
|
|
|
|
.pr-agenda-time {
|
|
color: var(--pr-muted);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
.pr-agenda-what {
|
|
padding-inline-start: 2mm;
|
|
border-inline-start: 1mm solid var(--chip, #3b82f6);
|
|
print-color-adjust: exact;
|
|
-webkit-print-color-adjust: exact;
|
|
}
|
|
|
|
.pr-agenda-title {
|
|
font-weight: 600;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.pr-agenda-row.is-inactive .pr-agenda-title {
|
|
color: var(--pr-muted);
|
|
}
|
|
|
|
.pr-agenda-row.is-cancelled .pr-agenda-title {
|
|
text-decoration: line-through;
|
|
}
|
|
|
|
.pr-agenda-meta {
|
|
color: var(--pr-muted);
|
|
font-size: 8.5pt;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.pr-empty {
|
|
margin-top: 6mm;
|
|
color: var(--pr-muted);
|
|
}
|
|
|
|
.pr-task-row {
|
|
grid-template-columns: 4mm minmax(0, 1fr) 34mm 20mm;
|
|
align-items: start;
|
|
}
|
|
|
|
.pr-checkbox {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 3.6mm;
|
|
height: 3.6mm;
|
|
margin-top: 0.5mm;
|
|
border: 0.3mm solid #333;
|
|
border-radius: 0.5mm;
|
|
font-size: 7pt;
|
|
line-height: 1;
|
|
}
|
|
|
|
.pr-task-title {
|
|
font-weight: 500;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.pr-task-row.is-done .pr-task-title {
|
|
color: var(--pr-muted);
|
|
text-decoration: line-through;
|
|
}
|
|
|
|
.pr-task-meta {
|
|
color: var(--pr-muted);
|
|
font-size: 8.5pt;
|
|
}
|
|
|
|
.pr-column-heads {
|
|
display: grid;
|
|
gap: 3mm;
|
|
padding-bottom: 1mm;
|
|
border-bottom: 0.3mm solid var(--pr-rule);
|
|
color: var(--pr-muted);
|
|
font-size: 7.5pt;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
break-after: avoid;
|
|
}
|
|
|
|
.pr-contact-row {
|
|
grid-template-columns: 27% 31% 18% minmax(0, 1fr);
|
|
padding-block: 0.8mm;
|
|
font-size: 8.5pt;
|
|
}
|
|
|
|
.pr-contact-row > *,
|
|
.pr-member-row > * {
|
|
min-width: 0;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.pr-contact-name {
|
|
font-weight: 600;
|
|
}
|
|
|
|
.pr-letter {
|
|
margin: 3.5mm 0 0;
|
|
padding-bottom: 0.8mm;
|
|
border-bottom: 0.3mm solid var(--pr-rule);
|
|
font-size: 10pt;
|
|
font-weight: 700;
|
|
break-after: avoid;
|
|
}
|
|
|
|
/* ---- One-item sheets (contact, group, directory entry, event) ------------ */
|
|
|
|
.pr-sheet {
|
|
font-size: 10.5pt;
|
|
}
|
|
|
|
.pr-sheet-head {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6mm;
|
|
padding-bottom: 5mm;
|
|
border-bottom: 0.3mm solid var(--pr-rule);
|
|
}
|
|
|
|
.pr-sheet-head h1 {
|
|
margin: 0;
|
|
font-size: 18pt;
|
|
font-weight: 600;
|
|
line-height: 1.2;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.pr-sheet-sub {
|
|
margin: 1mm 0 0;
|
|
color: var(--pr-muted);
|
|
}
|
|
|
|
.pr-swatch {
|
|
flex: none;
|
|
width: 5mm;
|
|
height: 5mm;
|
|
border-radius: 1mm;
|
|
background: var(--chip, #3b82f6);
|
|
print-color-adjust: exact;
|
|
-webkit-print-color-adjust: exact;
|
|
}
|
|
|
|
.pr-photo {
|
|
flex: none;
|
|
width: 25mm;
|
|
height: 25mm;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.pr-photo.is-placeholder {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: #e5e7eb;
|
|
color: #4b5563;
|
|
font-size: 30pt;
|
|
font-weight: 600;
|
|
print-color-adjust: exact;
|
|
-webkit-print-color-adjust: exact;
|
|
}
|
|
|
|
.pr-sheet section {
|
|
margin-top: 6mm;
|
|
break-inside: avoid;
|
|
}
|
|
|
|
.pr-sheet h2 {
|
|
margin: 0 0 2mm;
|
|
color: var(--pr-muted);
|
|
font-size: 8.5pt;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
break-after: avoid;
|
|
}
|
|
|
|
.pr-dl {
|
|
display: grid;
|
|
grid-template-columns: 38mm minmax(0, 1fr);
|
|
column-gap: 5mm;
|
|
row-gap: 1.6mm;
|
|
margin: 0;
|
|
}
|
|
|
|
.pr-dl > dt {
|
|
color: var(--pr-muted);
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.pr-dl > dd {
|
|
margin: 0;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.pr-text {
|
|
margin: 0;
|
|
white-space: pre-wrap;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
/* A long note or description may run over pages; its sections must not be
|
|
kept whole then. */
|
|
.pr-sheet section.pr-flow {
|
|
break-inside: auto;
|
|
}
|
|
|
|
.pr-member-row {
|
|
grid-template-columns: 34% 40% minmax(0, 1fr);
|
|
font-size: 9.5pt;
|
|
}
|
|
|
|
.pr-status {
|
|
color: var(--pr-muted);
|
|
white-space: nowrap;
|
|
}
|