/* ========================================================================== ccc.css — annotated demolition survey (behavior-preserving rewrite) ========================================================================== Sorted into nine concerns; each banner carries an ASSUMES: line naming the tokens and images it depends on. Within any equal-specificity collision set, relative source order is preserved verbatim. ========================================================================== */ /* ========================================================================== 1. DESIGN TOKENS ========================================================================== The desktop layout is a fixed lattice drawn around two images: header.png (909px wide, 145px tall) and left_column.png (continues the header artwork down the left menu band via a wrapper-covering ::before). Change these tokens and the two images must be regenerated — that IS the redesign. NOTE: custom properties cannot appear in @media conditions, so the 1015/1016 breakpoint below stays a literal pair. Its provenance is unexplained (roughly --page-width plus a margin allowance). ========================================================================== */ :root { --page-width: 909px; /* header.png's drawn width; the wrapper. Decomposes: 185 left band (135 col + 50 pad) + 490 center at left 200 + 210 right band (155 col + 55 pad) at left 690. 690 + 210 = 900: 9px absorbed silently at the right edge. */ --header-height: 145px; /* header.png's pixel height; search box and light-mode toggle hang from its bottom edge. */ --left-col-width: 135px; /* left band = this + --left-col-pad = 185px */ --left-col-pad: 50px; --center-left: 200px; /* 15px gutter beyond the 185px left band */ --center-width: 490px; --right-left: 690px; /* = --center-left + --center-width */ --right-width: 155px; /* right band = this + --right-pad = 210px */ --right-pad: 55px; --search-left: 676px; /* provenance unknown; sits 14px left of --right-left */ --toggle-left: 816px; /* provenance unknown; 140px right of --search-left */ --burger-right: 54px; /* provenance unknown */ /* Paper treatment (document thumbs and cards). Light-mode defaults; the effective-dark overrides live with the scheme logic in section 3 -- the one place toggle-awareness is implemented. */ --paper-edge: rgba(128, 128, 128, 0.4); --paper-shadow: 2px 3px 8px rgba(0, 0, 0, 0.25); } /* ========================================================================== 2. RESET & DOCUMENT SCAFFOLD ========================================================================== ASSUMES: nothing from the lattice. Element defaults and generic utilities only. ========================================================================== */ html { height: 100%; line-height: 1.6rem; } body { margin: 0; padding: 0; text-align: center; font-family: Verdana, Helvetica, Arial, sans-serif; background-color: Canvas; color: color-mix(in srgb, CanvasText, #808080 25%); hyphens: auto; color-scheme: light dark; min-height: 100%; height: 100%; } img { max-width: 100%; } pre { overflow: auto; } li { line-height: 1.5rem; margin-block-start: 1rem; margin-block-end: 1rem; } dt { font-weight: bold; margin-bottom: 1em; } dd { margin-bottom: 1em; } .pagination { margin-bottom: .5rem; } + /* Single caller: _headline_image.html.erb's image-count caption + ("N Bilder"), shown only when a gallery has more than one image. */ .right { text-align: right; } .hide-me { display: none; } .no_break { white-space: nowrap } /* ========================================================================== 3. COLOR SCHEME & LIGHT/DARK TOGGLE ========================================================================== ASSUMES: --header-height, --toggle-left (desktop toggle position); header.png and left_column.png (the invert(50%) treatment); the nonced inline restore script in the layout that re-checks #light-mode before first paint (the JS contract: checkbox id "light-mode", state persisted by the script). Symmetric blocks: each scheme inverts when the toggle is checked. Also owns the --paper-* effective-dark overrides (defaults in section 1). ========================================================================== */ @media (prefers-color-scheme: light) { body:has(#light-mode:checked) { color-scheme: dark; --paper-edge: rgba(200, 200, 200, 0.35); --paper-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06), 4px 6px 16px rgba(0, 0, 0, 0.8); } #light-mode + label[for=light-mode]:before { content: '🌙'; } #light-mode:checked + label[for=light-mode]:before { content: '☀️'; } /* The header images were set in the before times. Let them shine in dark mode, too */ body:has(#light-mode:checked) #header img, body:has(#light-mode:checked) div#left_column::before { filter: invert(50%); } } @media (prefers-color-scheme: dark) { body:has(#light-mode:checked) { color-scheme: light; } body:not(:has(#light-mode:checked)) { --paper-edge: rgba(200, 200, 200, 0.35); --paper-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06), 4px 6px 16px rgba(0, 0, 0, 0.8); } #light-mode + label[for=light-mode]:before { content: '☀️'; } #light-mode:checked + label[for=light-mode]:before { content: '🌙'; } /* The header images were set in the before times. Let them shine in dark mode, too */ body:not(:has(#light-mode:checked)) #header img, body:not(:has(#light-mode:checked)) div#left_column::before { filter: invert(50%); } } input#light-mode[type="checkbox"] { display: none; } label[for=light-mode] { font-size: 25px; user-select: none; cursor: pointer; filter: grayscale(1) contrast(10%); } /* Light and dark mode button magic */ @media(max-width:1015px) { div#light-mode-div { position: absolute; left: 170px; /* mobile toolbar offset; provenance unknown — anchors to the viewport, not #toolbox (see section 5) */ } } @media(min-width:1016px) { div#light-mode-div { position: absolute; top: var(--header-height); /* bottom edge of header.png */ left: var(--toggle-left); } } /* ========================================================================== 4. LINKS & HEADINGS ========================================================================== ASSUMES: nothing from the lattice. Site-wide type and link colors; the orange is the one brand color that survives theming. ========================================================================== */ a { color: #F8921E; text-decoration: none; } a:hover { color: #5b8ca7; } h2 { font-size: 1.5rem; font-family: Helvetica, Arial, sans-serif; line-height: 1.75rem; } h3 { font-size: 1.3rem; text-decoration: none; } h4 { font-size: 1.0rem; text-decoration: none; } h1, h2, h3, h4 { word-wrap: anywhere; hyphens:auto; } /* ========================================================================== 5. LAYOUT GRID ========================================================================== ASSUMES: the full token lattice; header.png (drawn width = --page-width, height = --header-height); left_column.png (continues the header art down the left band via the ::before at z-index -10). KNOWN STRUCTURAL DEBT: all three columns are position:absolute on desktop, but #footer lives INSIDE #center_column — a long sidebar can overflow past the footer. The column-height assumption is nowhere enforced. MOBILE ANCHORING: on max-width, #wrapper has no position, so the absolutely positioned toolbox children (#burger-div, #search, #light-mode-div) anchor to the viewport, not to #toolbox. ========================================================================== */ @media(min-width:1016px) { div#wrapper { position: relative; width: var(--page-width); /* header.png's drawn width */ margin: 0 auto 0 auto; text-align: left; min-height: 100%; } .break-mobile { display: block; } } /* Header */ #header img, #header > a { display: block; line-height: 0; } div#header img { border: none; } #left_column { line-height: 1.5em; } @media(min-width:1016px) { div#left_column::before { content: " "; position: absolute; left: 0; top: 0; width: 100%; height: 100%; box-sizing: border-box; background-image: url(/images/left_column.png); background-position: top right; background-repeat: no-repeat; z-index: -10; } div#left_column { position: absolute; left: 0px; width: var(--left-col-width); min-height: 100px; text-align: right; padding-right: var(--left-col-pad); /* left band total: 185px */ } div#left_column > a { font-size: 0.8rem; } } div#center_column { padding-bottom: 40px; } @media(max-width: 1015px) { div#center_column { padding: 0 15px 40px 15px; } } @media(min-width: 1016px) { div#center_column { position: absolute; background-color: Canvas; left: var(--center-left); width: var(--center-width); } } @media(min-width:1016px) { div#right_column { position: absolute; background-color: Canvas; padding-left: var(--right-pad); left: var(--right-left); /* = center-left + center-width */ width: var(--right-width); /* right band total: 210px; 690 + 210 = 900, 9px short of --page-width, absorbed silently */ height: 100px; } } /* Mobile toolbar strip. */ @media(max-width:1015px) { #toolbox { height: 30px; } } .admin_edit_link svg { width: 1em; height: 1em; vertical-align: -0.125em; } /* Footer */ #footer { border-bottom: 1px solid color-mix(in srgb, CanvasText, Canvas 60%); border-top: 1px solid color-mix(in srgb, CanvasText, Canvas 60%); bottom: 0; color: CanvasText; } #footer p { margin: .5rem auto; } #footer a { margin-left: 1rem; margin-right: 1rem; color: CanvasText; } /* ========================================================================== 6. MAIN NAVIGATION & BURGER MENU ========================================================================== ASSUMES: --burger-right; the checkbox-hack markup order in the layout (#toolbox precedes #left_column — the `#toolbox ~ #left_column` sibling selectors break if the layout reorders them); left_column.png behind the desktop nav. Mobile menu is pure CSS: .menu-checkbox state drives both the burger-to-X morph and the menu slide. COLLISION SET (order preserved): div.main_navigation ul base rule before its min-width override — the override's `padding: 0` must win. ========================================================================== */ div.main_navigation ul { margin-left: 0; padding-left: 15px; /* dead duplicate `padding-left: 0` removed */ padding-right: 15px; text-align: left; } @media(max-width:1015px) { div.main_navigation li:not(:first-child):before { content: '•'; margin-left: .3rem; margin-right: .6rem; } div.main_navigation li { list-style-type: none; display: inline-block; line-height: .75rem; } } @media(min-width:1016px) { div.main_navigation ul { padding: 0; text-align: right; } div.main_navigation li { list-style-type: none; line-height: 1.45em; } } div.main_navigation a { text-decoration: none; hyphens: none; } div.main_navigation a.inactive:hover, div#left_column span.inactive:hover { color: color-mix(in srgb, CanvasText, #808080 50%); } div.main_navigation a.active:before { content: "▸"; } div.main_navigation a.active { color: CanvasText; text-decoration: none; } div.main_navigation a.inactive, div.main_navigation span.inactive, div#left_column span.inactive { color: color-mix(in srgb, CanvasText, #808080 25%); } .menu-checkbox { display: none; } .burger-menu { display: none; cursor: pointer; } #burger-div { position: absolute; right: var(--burger-right); /* anchors to the viewport on mobile, see section 5 */ } /* Mobile styles */ @media (max-width: 1015px) { .burger-menu { position: absolute; display: flex; flex-direction: column; transition: transform 0.3s ease, opacity 0.3s ease; } .burger-menu span { display: inline-flex; width: 26px; height: 4px; background: color-mix(in srgb, CanvasText, #808080 25%); border-radius: 2px; margin: 3px 0; transition: max-height 0.5s ease-in-out, opacity 0.5s ease-in-out, transform 0.5s ease-in-out; } #left_column .main_navigation { width: 100%; position: relative; } #toolbox ~ #left_column .main_navigation ul { transition: max-height 0.2s ease-in-out, transform 0.4s ease-in-out, opacity 0.4s ease; overflow: hidden; text-align: center; } #toolbox ~ #left_column .main_navigation:first-of-type ul { transform: translateY(-200px); max-height: 0; opacity: 0; z-index: -10; } /* Show menu when checkbox is checked */ #toolbox:has(.menu-checkbox:checked) ~ #left_column .main_navigation ul { max-height: 400px; opacity: 1; transform: translateY(0); } .menu-checkbox:checked + .burger-menu span:nth-child(1) { transform: translateY(10px) rotate(45deg); } .menu-checkbox:checked + .burger-menu span:nth-child(2) { opacity: 0; } .menu-checkbox:checked + .burger-menu span:nth-child(3) { transform: translateY(-10px) rotate(-45deg); } } /* ========================================================================== 7. SEARCH ========================================================================== ASSUMES: --header-height, --search-left (desktop box hangs from header.png's bottom edge); viewport anchoring on mobile (section 5). ========================================================================== */ /* Search bar */ @media(min-width:1016px) { div#search { position: absolute; top: var(--header-height); /* bottom edge of header.png */ left: var(--search-left); height: 25px; vertical-align: top; } } @media(max-width:1015px) { div#search { position: absolute; left: 25px; /* mobile toolbar offset; anchors to the viewport */ height: 25px; } } div#search input { color: CanvasText !important; } div#search input[type=search], div#search input[type=text] { display: block; padding: 2px; margin: 0px; height: 25px; width: 132px; line-height: 20px; border: solid #808080 1px; background-color: Canvas; border-radius: 5px; margin-right: 5px; text-indent: 0.5rem; } /* ========================================================================== 8. SIDEBAR WIDGETS (calendar, tags, featured, open erfas) ========================================================================== ASSUMES: right-column geometry from section 5; div.main_navigation h2 also picks up the grouped border rule below. COLLISION SET (order preserved verbatim): the grouped h2 border rule, then the same-specificity div#frontpage_calendar h2 override (border-top: none), then the min-width block that re-adds a border-top for desktop. Moving the override above the group rule would grow a border on the calendar heading. ========================================================================== */ div#frontpage_calendar { display: none; margin-top: 10px; } @media(min-width:1016px) { div#frontpage_calendar { margin-top: 30px; } } div#frontpage_calendar h2, div#tags h2, div#featured_articles h2, div#open_erfas_today h2, div.main_navigation h2 { border-top: none; border-bottom: 1px solid color-mix(in srgb, CanvasText, Canvas 60%); font-size: 1.1em; padding-top: 2px; padding-bottom: 2px; } div#frontpage_calendar h2 { display: none; border-top: none; margin-left: auto; margin-right: auto; padding-left: 0.5em; padding-right: 0.5em; margin-top: 0; } div#open_erfas_today li { margin-top: 8px; margin-bottom: 8px; line-height: 1.25; } div#open_erfas_today .event_time { font-style: italic; font-family: Georgia; color: color-mix(in srgb, CanvasText, #808080); } @media(min-width:1016px) { div#frontpage_calendar h2, div#tags h2, div#featured_articles h2, div#open_erfas_today h2 { font-size: 1rem; } div#frontpage_calendar h2 { display: block; border-top: 1px solid color-mix(in srgb, CanvasText, Canvas 60%); padding: 2px 0; } } div#frontpage_calendar ul, div#tags ul, div#featured_articles ul, div#open_erfas_today ul { padding: 0px; font-size: 0.9rem; line-height: 1.5em; } div#featured_articles ul { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; padding: 0; } div#featured_articles li { margin: 0; } div#featured_articles img { max-width: 100%; height: auto; opacity: .85; } div#featured_articles a:hover img { opacity: 1; } div#frontpage_calendar li { margin-bottom: 20px; } div#frontpage_calendar li, div#tags li, div#featured_articles li, div#open_erfas_today li { list-style-type: none; } div#frontpage_calendar li a, div#tags li a, div#featured_articles li a, div#open_erfas_today li a { text-decoration: none; color: color-mix(in srgb, CanvasText, #808080 25%); } div#frontpage_calendar li a:hover, div#tags li a:hover, div#featured_articles li a:hover { text-decoration: none; color: color-mix(in srgb, CanvasText, #808080 50%); } /* We don't want the only colourful thing on the site to be pointing * somewhere else */ div#featured_articles img { filter: grayscale(1); } div#tags ul { display: flex; flex-wrap: wrap; gap: 0.2rem 0.9rem; } div#tags li { list-style-type: none; margin: 0; line-height: 1.4; } @media(max-width:1015px) { div#tags ul, div#featured_articles ul { justify-content: center; } } /* ========================================================================== 9. ARTICLE CONTENT ========================================================================== ASSUMES: center-column geometry from section 5; TinyMCE emits the inline-image classes (style-src unsafe-inline in the CSP exists partly for its img[style] output). ========================================================================== */ /* Main section */ .article, .article_partial { text-align: left; } div#center_column h1 { font-size: 1.5em; line-height: 1.2; } div#center_column h2 a { color: CanvasText; text-decoration: none; } div#center_column h2 a:hover { color: color-mix(in srgb, CanvasText, #808080 50%); } div#center_column h1.headline, div#center_column h2.headline { margin-top: 10px; } div#center_column h1.headline { font-size: 1.5em; } div#center_column .article_partial h2.headline { border-top: 1px solid color-mix(in srgb, CanvasText, Canvas 70%); padding-top: 30px; margin-bottom: 0.3rem; } /* except for erfa list */ div#center_column .chapter_partial h2.headline { border-top: none; } div#center_column .date_and_title_partial h2.headline { border-top: none; font-size 1.3rem; padding: 0.2rem 0 0 0; margin: 0; } .date_and_title_partial:nth-child(odd of .date_and_title_partial) { background-color: color-mix(in srgb, CanvasText, Canvas 94%); border: solid 1px color-mix(in srgb, CanvasText, Canvas 94%);; border-radius: 6px; } div.article_partial h2 a { text-decoration: none; } div.article_partial { margin-bottom: 30px; } div.article_partial.date_and_title_partial { position: relative; padding: 0.35rem 0.6rem 1rem; margin-bottom: 0; min-height: 4rem; } .date_and_title_partial h2.headline a::after { content: ""; position: absolute; inset: 0; } div.article_partial p.excerpt { color: CanvasText; } div.author_and_date { font-style: italic; font-family: Georgia; color: color-mix(in srgb, CanvasText, #808080); padding-top: .2rem; padding-bottom: .8rem; } .chapter_partial_layout { display: flow-root; } .chapter_thumbnail { float: right; margin: 0.5rem 0 8px 12px; } .chapter_thumbnail img { max-width: 150px; height: auto; border-radius: 4px; display: block; } div#center_column .chapter_partial h2.headline { border-top: none; padding-top: 0; } div#center_column .chapter_partial + .chapter_partial { border-top: 1px solid color-mix(in srgb, CanvasText, Canvas 70%); margin-top: 1.5rem; padding-top: 1.5rem; } .article_partial_layout { display: flow-root; } .article_thumbnail { float: right; margin: 0.5rem 0 8px 12px; } .article_thumbnail img { width: 116px; height: auto; min-height: 82px; /* 116 / sqrt(2): wider than DIN landscape crops */ max-height: 164px; /* 116 * sqrt(2): taller than DIN portrait crops */ object-fit: cover; display: block; border-radius: 4px; border: 1px solid var(--paper-edge); box-shadow: var(--paper-shadow); } .article_partial_layout .excerpt { margin-top: 0; } .inline-image--full { width: 100%; margin: 1rem 0; } .inline-image--half { width: 48%; margin-bottom: 1rem; } .inline-image--left { float: left; margin-right: 1rem; } .inline-image--right { float: right; margin-left: 1rem; } #asset_credits .asset_credit_block { display: none; } #asset_credits .asset_credit_block.headline_credit { display: block; } #asset_credits { border-top: dotted 1px color-mix(in srgb, CanvasText, Canvas 60%); } #asset_credits, .right { font-style: italic; font-family: Georgia; font-size: 0.9rem; color: color-mix(in srgb, CanvasText, #808080); } .glightbox-clean .gslide-description { background: Canvas !important; } .glightbox-clean .gslide-title, .glightbox-clean .gslide-desc { color: CanvasText !important; } .headline_document_card { display: flex; align-items: flex-end; gap: 1.5em; margin: 1.5em 0; text-decoration: none; } .headline_document_card_thumb { border: 1px solid var(--paper-edge); box-shadow: var(--paper-shadow); max-width: 180px; height: auto; } .headline_document_card_info { display: flex; flex-direction: column; gap: 0.3em; padding-top: 0.5em; padding-bottom: 0.5em; } .headline_document_card_titlerow { display: flex; align-items: center; gap: 0.4em; font-weight: bold; } .headline_document_card_meta { font-size: 0.85em; font-weight: normal; color: rgba(128, 128, 128, 0.95); } .related_documents { margin-top: 1rem; } .related_documents_label { font-style: italic; font-family: Georgia; font-size: 0.9rem; color: color-mix(in srgb, CanvasText, #808080); margin-bottom: 0.3rem; } .related_documents_list { list-style: none; padding: 0; margin: 0; } .related_document_link { display: inline-flex; align-items: center; gap: 0.4rem; text-decoration: none; }